001/*
002 * #%L
003 * Netarchivesuite - deploy
004 * %%
005 * Copyright (C) 2005 - 2018 The Royal Danish Library, 
006 *             the National Library of France and the Austrian National Library.
007 * %%
008 * This program is free software: you can redistribute it and/or modify
009 * it under the terms of the GNU Lesser General Public License as
010 * published by the Free Software Foundation, either version 2.1 of the
011 * License, or (at your option) any later version.
012 * 
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Lesser Public License for more details.
017 * 
018 * You should have received a copy of the GNU General Lesser Public
019 * License along with this program.  If not, see
020 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
021 * #L%
022 */
023package dk.netarkivet.deploy;
024
025import java.io.File;
026import java.io.FilenameFilter;
027import java.io.IOException;
028import java.nio.charset.Charset;
029
030
031import org.apache.commons.cli.CommandLine;
032import org.apache.commons.cli.CommandLineParser;
033import org.apache.commons.cli.Option;
034import org.apache.commons.cli.Options;
035import org.apache.commons.cli.ParseException;
036import org.apache.commons.cli.PosixParser;
037import org.apache.commons.io.filefilter.FileFileFilter;
038
039import dk.netarkivet.common.utils.Settings;
040
041// JDK8-import
042//import java.util.Optional;
043
044
045/**
046 * The application that is run to generate install and start/stop scripts for all physical locations, machines and
047 * applications.
048 * <p>
049 * The actual deployment has to be done from an Linux/Unix machine, and this application should therefore not be run on
050 * Windows.
051 */
052public final class DeployApplication {
053
054    static {
055        Settings.addDefaultClasspathSettings(Constants.BUILD_COMPLETE_SETTINGS_FILE_PATH);
056    }
057
058    /** The configuration for this deploy. */
059    private static DeployConfiguration deployConfig;
060    /** Argument parameter. */
061    private static ArgumentParameters ap = new ArgumentParameters();
062    /** The deploy-config file. */
063    private static File deployConfigFile;
064    /** The NetarchiveSuite file. */
065    private static File netarchiveSuiteFile;
066    /** The security policy file. */
067    private static File secPolicyFile;
068    /** SLF4J xml configuration file. */
069    private static File slf4jConfigFile;
070    /** The database file. */
071    private static File dbFile;
072    /** The arguments for resetting tempDir. */
073    private static boolean resetDirectory;
074    /** The archive database file. */
075    private static File arcDbFile;
076    /** The folder with the external libraries to be deployed. */
077    private static File externalJarFolder;
078    /** The bitmagasin source directory. */
079    private static File bitmagasinSourceDirectory;
080
081    //private static Optional<File> defaultBundlerZip;
082    private static File defaultBundlerZip;
083    
084    /** The logo png file. */
085    private static File logoFile;
086    /** The menulogo png file. */
087    private static File menulogoFile;
088    
089    /**
090     * Private constructor to disallow instantiation of this class.
091     */
092    private DeployApplication() {
093    }
094
095    /**
096     * Run deploy.
097     *
098     * @param args The Command-line arguments in no particular order:
099     *
100     * -C The deploy configuration file (ends with .xml). -Z The NetarchiveSuite file to be unpacked (ends with .zip).
101     * -S The security policy file (ends with .policy). -L The logging property file (ends with .prop). -O [OPTIONAL]
102     * The output directory -D [OPTIONAL] The harvest definition database -T [OPTIONAL] The test arguments
103     * (httpportoffset, port, environmentName, mailReceiver) -R [OPTIONAL] For resetting the tempDir (takes arguments
104     * 'y' or 'yes') -E [OPTIONAL] Evaluating the deployConfig file (arguments: 'y' or 'yes') -A [OPTIONAL] For archive
105     * database. -J [OPTIONAL] For deploying with external jar files. Must be the total path to the directory containing
106     * jar-files. -l [OPTIONAL] for logo png file. -m [OPTIONAL] for menulogo png file 
107     * These external files will be placed on every machine, and they have to manually be put into the
108     * classpath, where they should be used.
109     */
110    public static void main(String[] args) {
111        try {
112            // Make sure the arguments can be parsed.
113            if (!ap.parseParameters(args)) {
114                System.err.print(Constants.MSG_ERROR_PARSE_ARGUMENTS);
115                System.out.println(ap.listArguments());
116                System.exit(1);
117            }
118
119            // Check arguments
120            if (ap.getCommandLine().getOptions().length < Constants.ARGUMENTS_REQUIRED) {
121                System.err.print(Constants.MSG_ERROR_NOT_ENOUGH_ARGUMENTS);
122                System.out.println();
123                System.out.println("Use DeployApplication with following arguments:");
124                System.out.println(ap.listArguments());
125                System.out.println("outputdir defaults to ./environmentName (set in config file)");
126                System.exit(1);
127            }
128            // test if more arguments than options is given
129            if (args.length > ap.getOptions().getOptions().size()) {
130                System.err.print(Constants.MSG_ERROR_TOO_MANY_ARGUMENTS);
131                System.out.println();
132                System.out.println("Maximum " + ap.getOptions().getOptions().size() + "arguments.");
133                System.exit(1);
134            }
135
136            // Retrieving the configuration filename
137            String deployConfigFileName = ap.getCommandLine().getOptionValue(Constants.ARG_CONFIG_FILE);
138            // Retrieving the NetarchiveSuite filename
139            String netarchiveSuiteFileName = ap.getCommandLine().getOptionValue(Constants.ARG_NETARCHIVE_SUITE_FILE);
140            // Retrieving the security policy filename
141            String secPolicyFileName = ap.getCommandLine().getOptionValue(Constants.ARG_SECURITY_FILE);
142            // Retrieving the SLF4J xml filename
143            String slf4jConfigFileName = ap.getCommandLine().getOptionValue(Constants.ARG_SLF4J_CONFIG_FILE);
144            // Retrieving the output directory name
145            String outputDir = ap.getCommandLine().getOptionValue(Constants.ARG_OUTPUT_DIRECTORY);
146            // Retrieving the database filename
147            String databaseFileName = ap.getCommandLine().getOptionValue(Constants.ARG_DATABASE_FILE);
148            // Retrieving the test arguments
149            String testArguments = ap.getCommandLine().getOptionValue(Constants.ARG_TEST);
150            // Retrieving the reset argument
151            String resetArgument = ap.getCommandLine().getOptionValue(Constants.ARG_RESET);
152            // Retrieving the evaluate argument
153            String evaluateArgument = ap.getCommandLine().getOptionValue(Constants.ARG_EVALUATE);
154            // Retrieve the archive database filename.
155            String arcDbFileName = ap.getCommandLine().getOptionValue(Constants.ARG_ARC_DB);
156            // Retrieves the jar-folder name.
157            String jarFolderName = ap.getCommandLine().getOptionValue(Constants.ARG_JAR_FOLDER);
158            // Retrieves the bitmagasin source directory name.
159            String bitmagSourceDir = ap.getCommandLine().getOptionValue(Constants.ARG_BITMAG_SOURCE_DIR);
160            // Retrieves the logo filename.
161            String logoFilename = ap.getCommandLine().getOptionValue(Constants.ARG_LOGO);
162            // Retrieves the menulogo filename.
163            String menulogoFilename = ap.getCommandLine().getOptionValue(Constants.ARG_MENULOGO);
164            
165            // Retrieves the source encoding.
166            // If not specified get system default
167            String sourceEncoding = ap.getCommandLine().getOptionValue(Constants.ARG_SOURCE_ENCODING);
168            String msgTail = "";
169            if (sourceEncoding == null || sourceEncoding.isEmpty()) {
170                sourceEncoding = Charset.defaultCharset().name();
171                msgTail = " (defaulted)";
172            }
173            System.out.println("Will read source files using encoding '" + sourceEncoding + "'" + msgTail);
174
175            // check deployConfigFileName and retrieve the corresponding file
176            initConfigFile(deployConfigFileName);
177
178            // check netarchiveSuiteFileName and retrieve the corresponding file
179            initNetarchiveSuiteFile(netarchiveSuiteFileName);
180
181            // check secPolicyFileName and retrieve the corresponding file
182            initSecPolicyFile(secPolicyFileName);
183
184            initSLF4JXmlFile(slf4jConfigFileName);
185
186            // check database
187            initDatabase(databaseFileName);
188
189            // check and apply the test arguments
190            initTestArguments(testArguments);
191
192            // check reset arguments.
193            initReset(resetArgument);
194
195            // evaluates the config file
196            initEvaluate(evaluateArgument, sourceEncoding);
197
198            // check the archive database
199            initArchiveDatabase(arcDbFileName);
200
201            // check the external jar-files library folder.
202            initJarFolder(jarFolderName);
203
204            // check the bitmagasin source directory.
205            initBitmagSourceDir(bitmagSourceDir);
206
207            //initBundlerZip(Optional.ofNullable(
208            //        ap.getCommandLine().getOptionValue(Constants.ARG_DEFAULT_BUNDLER_ZIP)));
209            initBundlerZip(ap.getCommandLine().getOptionValue(Constants.ARG_DEFAULT_BUNDLER_ZIP));
210            
211            // check the logo files
212            initLogos(logoFilename, menulogoFilename);
213            
214            // Make the configuration based on the input data
215            deployConfig = new DeployConfiguration(deployConfigFile, netarchiveSuiteFile, secPolicyFile,
216                    slf4jConfigFile, outputDir, dbFile, arcDbFile, resetDirectory, externalJarFolder, sourceEncoding,
217                    defaultBundlerZip, logoFile, menulogoFile, bitmagasinSourceDirectory);
218
219            // Write the scripts, directories and everything
220            deployConfig.write();
221        } catch (SecurityException e) {
222            // This problem should only occur in tests -> thus not err message.
223            System.out.println("SECURITY ERROR: ");
224            e.printStackTrace();
225        } catch (Throwable e) {
226            System.err.println("DEPLOY APPLICATION ERROR: ");
227            e.printStackTrace();
228        }
229    }
230
231    /**
232     * Checks the configuration file argument and retrieves the file.
233     *
234     * @param deployConfigFileName The configuration file argument.
235     */
236    private static void initConfigFile(String deployConfigFileName) {
237        // check whether deploy-config file name is given as argument
238        if (deployConfigFileName == null) {
239            System.err.print(Constants.MSG_ERROR_NO_CONFIG_FILE_ARG);
240            System.out.println();
241            System.exit(1);
242        }
243        // check whether deploy-config file has correct extensions
244        if (!deployConfigFileName.endsWith(Constants.EXTENSION_XML_FILES)) {
245            System.err.print(Constants.MSG_ERROR_CONFIG_EXTENSION);
246            System.out.println();
247            System.exit(1);
248        }
249        // get the file
250        deployConfigFile = new File(deployConfigFileName);
251        // check whether the deploy-config file exists.
252        if (!deployConfigFile.exists()) {
253            System.err.print(Constants.MSG_ERROR_NO_CONFIG_FILE_FOUND);
254            System.out.println();
255            System.exit(1);
256        }
257    }
258
259    /**
260     * Checks the NetarchiveSuite file argument and retrieves the file.
261     *
262     * @param netarchiveSuiteFileName The NetarchiveSuite argument.
263     */
264    private static void initNetarchiveSuiteFile(String netarchiveSuiteFileName) {
265        // check whether NetarchiveSuite file name is given as argument
266        if (netarchiveSuiteFileName == null) {
267            System.err.print(Constants.MSG_ERROR_NO_NETARCHIVESUITE_FILE_ARG);
268            System.out.println();
269            System.exit(1);
270        }
271        // check whether the NetarchiveSuite file has correct extensions
272        if (!netarchiveSuiteFileName.endsWith(Constants.EXTENSION_ZIP_FILES)) {
273            System.err.print(Constants.MSG_ERROR_NETARCHIVESUITE_EXTENSION);
274            System.out.println();
275            System.exit(1);
276        }
277        // get the file
278        netarchiveSuiteFile = new File(netarchiveSuiteFileName);
279        // check whether the NetarchiveSuite file exists.
280        if (!netarchiveSuiteFile.isFile()) {
281            System.err.print(Constants.MSG_ERROR_NO_NETARCHIVESUITE_FILE_FOUND);
282            System.out.println();
283            System.out.println("Couldn't find file: " + netarchiveSuiteFile.getAbsolutePath());
284            System.exit(1);
285        }
286    }
287
288    /**
289     * Checks the security policy file argument and retrieves the file.
290     *
291     * @param secPolicyFileName The security policy argument.
292     */
293    private static void initSecPolicyFile(String secPolicyFileName) {
294        // check whether security policy file name is given as argument
295        if (secPolicyFileName == null) {
296            System.err.print(Constants.MSG_ERROR_NO_SECURITY_FILE_ARG);
297            System.out.println();
298            System.exit(1);
299        }
300        // check whether security policy file has correct extensions
301        if (!secPolicyFileName.endsWith(Constants.EXTENSION_POLICY_FILES)) {
302            System.err.print(Constants.MSG_ERROR_SECURITY_EXTENSION);
303            System.out.println();
304            System.exit(1);
305        }
306        // get the file
307        secPolicyFile = new File(secPolicyFileName);
308        // check whether the security policy file exists.
309        if (!secPolicyFile.exists()) {
310            System.err.print(Constants.MSG_ERROR_NO_SECURITY_FILE_FOUND);
311            System.out.println();
312            System.out.println("Couldn't find file: " + secPolicyFile.getAbsolutePath());
313            System.exit(1);
314        }
315    }
316
317    /**
318     * Checks the SLF4J config file argument and retrieves the file.
319     *
320     * @param slf4jXmlFileName The SLF4J config argument.
321     */
322    private static void initSLF4JXmlFile(String slf4jXmlFileName) {
323        // check whether SLF4J config file name is given as argument
324        if (slf4jXmlFileName == null) {
325            System.err.print(Constants.MSG_ERROR_NO_SLF4J_CONFIG_FILE_ARG);
326            System.out.println();
327            System.exit(1);
328        }
329        // check whether the SLF4J xml file has correct extensions
330        if (!slf4jXmlFileName.endsWith(Constants.EXTENSION_XML_FILES)) {
331            System.err.print(Constants.MSG_ERROR_SLF4J_CONFIG_EXTENSION);
332            System.out.println();
333            System.exit(1);
334        }
335        // get the file
336        slf4jConfigFile = new File(slf4jXmlFileName);
337        // check whether the SLF4J xml file exists.
338        if (!slf4jConfigFile.exists()) {
339            System.err.print(Constants.MSG_ERROR_NO_SLF4J_CONFIG_FILE_FOUND);
340            System.out.println();
341            System.out.println("Couldn't find file: " + slf4jConfigFile.getAbsolutePath());
342            System.exit(1);
343        }
344    }
345
346    /**
347     * Checks the database argument (if any) for extension and existence.
348     *
349     * @param databaseFileName The name of the database file.
350     */
351    private static void initDatabase(String databaseFileName) {
352        dbFile = null;
353        // check the extension on the database, if it is given as argument
354        if (databaseFileName != null) {
355            if (!databaseFileName.endsWith(Constants.EXTENSION_JAR_FILES)
356                    && !databaseFileName.endsWith(Constants.EXTENSION_ZIP_FILES)) {
357                System.err.print(Constants.MSG_ERROR_DATABASE_EXTENSION);
358                System.out.println();
359                System.exit(1);
360            }
361
362            // get the file
363            dbFile = new File(databaseFileName);
364            // check whether the database file exists.
365            if (!dbFile.isFile()) {
366                System.err.print(Constants.MSG_ERROR_NO_DATABASE_FILE_FOUND);
367                System.out.println();
368                System.out.println("Couldn't find file: " + dbFile.getAbsolutePath());
369                System.exit(1);
370            }
371        }
372    }
373
374    /**
375     * Checks the arguments for resetting the directory. Only the arguments 'y' or 'yes' resets the database directory.
376     * Default is 'no'.
377     * <p>
378     * If another argument than 'y', 'yes', 'n' or 'no' is given, an warning is given.
379     *
380     * @param resetArgument The argument for resetting given.
381     */
382    private static void initReset(String resetArgument) {
383        if (resetArgument != null) {
384            if (resetArgument.equalsIgnoreCase(Constants.YES_SHORT)
385                    || resetArgument.equalsIgnoreCase(Constants.YES_LONG)) {
386                // if positive argument, then set to true.
387                resetDirectory = true;
388            } else if (resetArgument.equalsIgnoreCase(Constants.NO_SHORT)
389                    || resetArgument.equalsIgnoreCase(Constants.NO_LONG)) {
390                // if negative argument, then set to false.
391                resetDirectory = false;
392            } else {
393                // if wrong argument, notify and set to false.
394                System.err.println(Constants.MSG_ERROR_RESET_ARGUMENT);
395                resetDirectory = false;
396            }
397        } else {
398            // if no arguments, then
399            resetDirectory = false;
400        }
401    }
402
403    /**
404     * Checks the arguments for evaluating the config file. Only the arguments 'y' or 'yes' is accepted for evaluation.
405     * Anything else (including argument set to null) does not evaluate the deployConfigFile.
406     *
407     * @param evaluateArgument The argument for evaluation.
408     * @param encoding the encoding to use to read from the input file
409     */
410    public static void initEvaluate(String evaluateArgument, String encoding) {
411        // check if argument is given and it is acknowledgement ('y' or 'yes')
412        if ((evaluateArgument != null)
413                && (!evaluateArgument.isEmpty())
414                && (evaluateArgument.equalsIgnoreCase(Constants.YES_SHORT) || evaluateArgument
415                        .equalsIgnoreCase(Constants.YES_LONG))) {
416            // if yes, then evaluate config file
417            EvaluateConfigFile evf = new EvaluateConfigFile(deployConfigFile, encoding);
418            evf.evaluate();
419        }
420    }
421
422    /**
423     * Checks the argument for the archive database.
424     *
425     * @param arcDbFileName The path to the archive database.
426     */
427    public static void initArchiveDatabase(String arcDbFileName) {
428        arcDbFile = null;
429        // check the extension on the database, if it is given as argument
430        if (arcDbFileName != null) {
431            if (!arcDbFileName.endsWith(Constants.EXTENSION_JAR_FILES)
432                    && !arcDbFileName.endsWith(Constants.EXTENSION_ZIP_FILES)) {
433                System.err.print(Constants.MSG_ERROR_BPDB_EXTENSION);
434                System.out.println();
435                System.exit(1);
436            }
437
438            // get the file
439            arcDbFile = new File(arcDbFileName);
440            // check whether the database file exists.
441            if (!arcDbFile.isFile()) {
442                System.err.print(Constants.MSG_ERROR_NO_BPDB_FILE_FOUND);
443                System.out.println();
444                System.out.println("Couldn't find file: " + arcDbFile.getAbsolutePath());
445                System.exit(1);
446            }
447        }
448    }
449
450    /**
451     * Checks the argument for the external jar-folder.
452     *
453     * @param folderName The path to the folder. Global path.
454     */
455    public static void initJarFolder(String folderName) {
456        externalJarFolder = null;
457        if (folderName != null && !folderName.isEmpty()) {
458            externalJarFolder = new File(folderName);
459
460            if (!externalJarFolder.isDirectory()) {
461                System.err.print(Constants.MSG_ERROR_NO_JAR_FOLDER);
462                System.out.println();
463                System.out.println("Couldn't find directory: " + externalJarFolder.getAbsolutePath());
464                System.exit(1);
465            }
466        }
467    }
468
469    /**
470     * Checks the argument for the bitmagasin source directory. Specifically, if specified, the folder must
471     *  - be a directory
472     *  - contain RepositorySettings.xml and ReferenceSettings.xml files
473     *  - contain exactly one .pem file, assumed to be the client certkey
474     *  No other validation is carried out (e.g. of the file formats)
475     *
476     * @param folderName The path to the folder.
477     */
478    public static void initBitmagSourceDir(String folderName) {
479        bitmagasinSourceDirectory = null;
480        if (folderName != null && !folderName.isEmpty()) {
481            bitmagasinSourceDirectory = new File(folderName);
482
483            if (!bitmagasinSourceDirectory.isDirectory()) {
484                System.err.print(Constants.MSG_ERROR_NO_BITMAG_FOLDER);
485                System.out.println();
486                System.out.println("Couldn't find directory: " + bitmagasinSourceDirectory.getAbsolutePath());
487                System.exit(1);
488            }
489            if (!(new File(bitmagasinSourceDirectory, Constants.REPOSITORY_SETTINGS_XML)).exists()) {
490                System.err.println("Bitmag client directory " + bitmagasinSourceDirectory.getAbsolutePath()
491                        + " does not contain a RepositorySettings.xml file.");
492                System.exit(1);
493            }
494            if (!(new File(bitmagasinSourceDirectory, "ReferenceSettings.xml")).exists()) {
495                System.err.println("Bitmag client directory " + bitmagasinSourceDirectory.getAbsolutePath()
496                        + " does not contain a RepositorySettings.xml file.");
497                System.exit(1);
498            }
499            int pemFiles = bitmagasinSourceDirectory.list((dir, name) -> name.endsWith(Constants.PEM)).length;
500            if (!(pemFiles == 1)) {
501                System.err.println("No unique client certkey (.pem file) found in " + bitmagasinSourceDirectory.getAbsolutePath());
502                System.exit(1);
503            }
504        }
505    }
506
507    /**
508     * Checks if the default bundler zip file exists if defined.
509     *
510     * @param defaultBundlerZipName The path to the default bundler zip file to use.
511     */
512    public static void initBundlerZip(String defaultBundlerZipName) {
513        if (defaultBundlerZipName != null) {
514            defaultBundlerZip = new File(defaultBundlerZipName);
515            if (!defaultBundlerZip.exists()) {
516                System.err.print(Constants.MSG_ERROR_NO_BUNDLER_ZIP_FILE);
517                System.out.println();
518                System.out.println("Couldn't find the default bundler file: " + defaultBundlerZip.getAbsolutePath());
519                System.exit(1);
520            }
521        }
522    }
523
524    /**
525     * Checks if the logo files exists
526     *
527     * @param logoFilename The absolute path to the logo png file.
528     * @param menulogoFilename The absoluet path to the menu logo png file.
529     */
530    public static void initLogos(String logoFilename, String menulogoFilename) {
531        if (logoFilename != null) {
532                logoFile = new File(logoFilename);
533                if (!logoFile.exists()) {
534                        logoFile = null;
535                }
536        }
537        
538        if (menulogoFilename != null) {
539                menulogoFile = new File(menulogoFilename);
540                if (!menulogoFile.exists()) {
541                        menulogoFile = null;
542                }
543        }
544    }
545    
546    /**
547     * Applies the test arguments.
548     * <p>
549     * If the test arguments are given correctly, the configuration file is loaded and changed appropriately, then
550     * written to a test configuration file.
551     * <p>
552     * The new test configuration file has the same name as the original configuration file, except ".xml" is replaced
553     * by "_text.xml". Thus "path/config.xml" -> "path/config_test.xml".
554     *
555     * @param testArguments The test arguments.
556     */
557    private static void initTestArguments(String testArguments) {
558        // test if any test arguments (if none, don't apply, just stop).
559        if (testArguments == null || testArguments.isEmpty()) {
560            return;
561        }
562
563        String[] changes = testArguments.split(Constants.REGEX_COMMA_CHARACTER);
564        if (changes.length != Constants.TEST_ARGUMENTS_REQUIRED) {
565            System.err.print(Constants.MSG_ERROR_TEST_ARGUMENTS);
566            System.out.println();
567            System.out.println(changes.length + " arguments was given and " + Constants.TEST_ARGUMENTS_REQUIRED
568                    + " was expected.");
569            System.out.println("Received: " + testArguments);
570            System.exit(1);
571        }
572
573        try {
574            CreateTestInstance cti = new CreateTestInstance(deployConfigFile);
575
576            // apply the arguments
577            cti.applyTestArguments(changes[Constants.TEST_ARGUMENT_OFFSET_INDEX],
578                    changes[Constants.TEST_ARGUMENT_HTTP_INDEX],
579                    changes[Constants.TEST_ARGUMENT_ENVIRONMENT_NAME_INDEX],
580                    changes[Constants.TEST_ARGUMENT_MAIL_INDEX]);
581
582            // replace ".xml" with "_test.xml"
583            String tmp = deployConfigFile.getPath();
584            // split this into two ("path/config.xml" = {"path/config", ".xml"})
585            String[] configFile = tmp.split(Constants.REGEX_DOT_CHARACTER);
586            // take the first part and add test ending
587            // ("path/config" + "_test.xml" = "path/config_test.xml")
588            String nameOfNewConfig = configFile[0] + Constants.TEST_CONFIG_FILE_REPLACE_ENDING;
589
590            // create and use new config file.
591            cti.createConfigurationFile(nameOfNewConfig);
592            deployConfigFile = new File(nameOfNewConfig);
593        } catch (IOException e) {
594            System.out.println("Error in test arguments: " + e);
595            System.exit(1);
596        }
597    }
598
599    /**
600     * Handles the incoming arguments.
601     */
602    private static class ArgumentParameters {
603        /** Options object for parameters. */
604        private Options options = new Options();
605        /** Parser for parsing the command line arguments. */
606        private CommandLineParser parser = new PosixParser();
607        /** The command line. */
608        private CommandLine cmd;
609        /** Whether the options has an argument. */
610        private static final boolean HAS_ARG = true;
611
612        /**
613         * Initialise options by setting legal parameters for batch jobs.
614         */
615        ArgumentParameters() {
616            options.addOption(Constants.ARG_CONFIG_FILE, HAS_ARG, "Config file.");
617            options.addOption(Constants.ARG_NETARCHIVE_SUITE_FILE, HAS_ARG, "The NetarchiveSuite package file.");
618            options.addOption(Constants.ARG_SECURITY_FILE, HAS_ARG, "Security property file.");
619            options.addOption(Constants.ARG_SLF4J_CONFIG_FILE, HAS_ARG, "SLF4J config file.");
620            options.addOption(Constants.ARG_OUTPUT_DIRECTORY, HAS_ARG, "[OPTIONAL] output directory.");
621            options.addOption(Constants.ARG_DATABASE_FILE, HAS_ARG, "[OPTIONAL] Database file.");
622            options.addOption(Constants.ARG_TEST, HAS_ARG, "[OPTIONAL] Tests arguments (offset for http port,"
623                    + " http port, environment name, mail receiver).");
624            options.addOption(Constants.ARG_RESET, HAS_ARG, "[OPTIONAL] Reset temp directory ('y' or 'yes'"
625                    + "means reset, anything else means do not reset."
626                    + " Different from 'y', 'yes', 'n' or 'no' gives" + " an error message.");
627            options.addOption(Constants.ARG_EVALUATE, HAS_ARG, "[OPTIONAL] Evaluate the config file.");
628            options.addOption(Constants.ARG_ARC_DB, HAS_ARG, "[OPTIONAL] The archive database file");
629            options.addOption(Constants.ARG_JAR_FOLDER, HAS_ARG, "[OPTIONAL] Installing the external jar library "
630                    + "files within the given folder.");
631            options.addOption(Constants.ARG_BITMAG_SOURCE_DIR, HAS_ARG, "[OPTIONAL] Manage distribution of the "
632                    + "Bitmagasin configuration directory to the harvester machines");
633            options.addOption(Constants.ARG_SOURCE_ENCODING, HAS_ARG, "[OPTIONAL] Encoding to use for source files.");
634            options.addOption(Constants.ARG_DEFAULT_BUNDLER_ZIP, HAS_ARG, "[OPTIONAL] The bundled harvester to use. "
635                    + "If not provided here the bundler needs to be provided in the settings for each (H3) harvester");
636            options.addOption(null, Constants.ARG_LOGO, HAS_ARG, "[OPTIONAL] The Logo png file to use. "
637                    + "(this is only working for Linux)");
638            options.addOption(null, Constants.ARG_MENULOGO, HAS_ARG, "[OPTIONAL] The Menulogo png file to use. "
639                    + "(this is only working for Linux)");
640        }
641
642        /**
643         * Parsing the input arguments.
644         *
645         * @param args The input arguments.
646         * @return Whether it parsed correctly or not.
647         */
648        Boolean parseParameters(String[] args) {
649            try {
650                // parse the command line arguments
651                cmd = parser.parse(options, args);
652            } catch (ParseException exp) {
653                System.out.println("Parsing error: " + exp);
654                return false;
655            }
656            return true;
657        }
658
659        /**
660         * Get the list of possible arguments with their description.
661         *
662         * @return The list describing the possible arguments.
663         */
664        String listArguments() {
665            StringBuilder res = new StringBuilder();
666            res.append(Constants.NEWLINE);
667            res.append(Constants.INIT_ARGUMENTS_LIST);
668            // add options
669            for (Object o : options.getOptions()) {
670                Option op = (Option) o;
671                res.append(Constants.NEWLINE);
672                res.append(Constants.DASH);
673                res.append(op.getOpt());
674                res.append(Constants.SPACE);
675                res.append(op.getDescription());
676            }
677            return res.toString();
678        }
679
680        /**
681         * For retrieving the options.
682         *
683         * @return The options.
684         */
685        public Options getOptions() {
686            return options;
687        }
688
689        /**
690         * For retrieving the commandLine.
691         *
692         * @return The cmd.
693         */
694        public CommandLine getCommandLine() {
695            return cmd;
696        }
697    }
698
699}