Java tutorial
/* * #%L * Netarchivesuite - deploy * %% * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, * the National Library of France and the Austrian National Library. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 2.1 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Lesser Public License for more details. * * You should have received a copy of the GNU General Lesser Public * License along with this program. If not, see * <http://www.gnu.org/licenses/lgpl-2.1.html>. * #L% */ package dk.netarkivet.deploy; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import dk.netarkivet.common.utils.Settings; // JDK8-import //import java.util.Optional; /** * The application that is run to generate install and start/stop scripts for all physical locations, machines and * applications. * <p> * The actual deployment has to be done from an Linux/Unix machine, and this application should therefore not be run on * Windows. */ public final class DeployApplication { static { Settings.addDefaultClasspathSettings(Constants.BUILD_COMPLETE_SETTINGS_FILE_PATH); } /** The configuration for this deploy. */ private static DeployConfiguration deployConfig; /** Argument parameter. */ private static ArgumentParameters ap = new ArgumentParameters(); /** The deploy-config file. */ private static File deployConfigFile; /** The NetarchiveSuite file. */ private static File netarchiveSuiteFile; /** The security policy file. */ private static File secPolicyFile; /** SLF4J xml configuration file. */ private static File slf4jConfigFile; /** The database file. */ private static File dbFile; /** The arguments for resetting tempDir. */ private static boolean resetDirectory; /** The archive database file. */ private static File arcDbFile; /** The folder with the external libraries to be deployed. */ private static File externalJarFolder; //private static Optional<File> defaultBundlerZip; private static File defaultBundlerZip; /** * Private constructor to disallow instantiation of this class. */ private DeployApplication() { } /** * Run deploy. * * @param args The Command-line arguments in no particular order: * * -C The deploy configuration file (ends with .xml). -Z The NetarchiveSuite file to be unpacked (ends with .zip). * -S The security policy file (ends with .policy). -L The logging property file (ends with .prop). -O [OPTIONAL] * The output directory -D [OPTIONAL] The harvest definition database -T [OPTIONAL] The test arguments * (httpportoffset, port, environmentName, mailReceiver) -R [OPTIONAL] For resetting the tempDir (takes arguments * 'y' or 'yes') -E [OPTIONAL] Evaluating the deployConfig file (arguments: 'y' or 'yes') -A [OPTIONAL] For archive * database. -J [OPTIONAL] For deploying with external jar files. Must be the total path to the directory containing * jar-files. These external files will be placed on every machine, and they have to manually be put into the * classpath, where they should be used. */ public static void main(String[] args) { try { // Make sure the arguments can be parsed. if (!ap.parseParameters(args)) { System.err.print(Constants.MSG_ERROR_PARSE_ARGUMENTS); System.out.println(ap.listArguments()); System.exit(1); } // Check arguments if (ap.getCommandLine().getOptions().length < Constants.ARGUMENTS_REQUIRED) { System.err.print(Constants.MSG_ERROR_NOT_ENOUGH_ARGUMENTS); System.out.println(); System.out.println("Use DeployApplication with following arguments:"); System.out.println(ap.listArguments()); System.out.println("outputdir defaults to ./environmentName (set in config file)"); System.exit(1); } // test if more arguments than options is given if (args.length > ap.getOptions().getOptions().size()) { System.err.print(Constants.MSG_ERROR_TOO_MANY_ARGUMENTS); System.out.println(); System.out.println("Maximum " + ap.getOptions().getOptions().size() + "arguments."); System.exit(1); } // Retrieving the configuration filename String deployConfigFileName = ap.getCommandLine().getOptionValue(Constants.ARG_CONFIG_FILE); // Retrieving the NetarchiveSuite filename String netarchiveSuiteFileName = ap.getCommandLine() .getOptionValue(Constants.ARG_NETARCHIVE_SUITE_FILE); // Retrieving the security policy filename String secPolicyFileName = ap.getCommandLine().getOptionValue(Constants.ARG_SECURITY_FILE); // Retrieving the SLF4J xml filename String slf4jConfigFileName = ap.getCommandLine().getOptionValue(Constants.ARG_SLF4J_CONFIG_FILE); // Retrieving the output directory name String outputDir = ap.getCommandLine().getOptionValue(Constants.ARG_OUTPUT_DIRECTORY); // Retrieving the database filename String databaseFileName = ap.getCommandLine().getOptionValue(Constants.ARG_DATABASE_FILE); // Retrieving the test arguments String testArguments = ap.getCommandLine().getOptionValue(Constants.ARG_TEST); // Retrieving the reset argument String resetArgument = ap.getCommandLine().getOptionValue(Constants.ARG_RESET); // Retrieving the evaluate argument String evaluateArgument = ap.getCommandLine().getOptionValue(Constants.ARG_EVALUATE); // Retrieve the archive database filename. String arcDbFileName = ap.getCommandLine().getOptionValue(Constants.ARG_ARC_DB); // Retrieves the jar-folder name. String jarFolderName = ap.getCommandLine().getOptionValue(Constants.ARG_JAR_FOLDER); // Retrieves the source encoding. // If not specified get system default String sourceEncoding = ap.getCommandLine().getOptionValue(Constants.ARG_SOURCE_ENCODING); String msgTail = ""; if (sourceEncoding == null || sourceEncoding.isEmpty()) { sourceEncoding = Charset.defaultCharset().name(); msgTail = " (defaulted)"; } System.out.println("Will read source files using encoding '" + sourceEncoding + "'" + msgTail); // check deployConfigFileName and retrieve the corresponding file initConfigFile(deployConfigFileName); // check netarchiveSuiteFileName and retrieve the corresponding file initNetarchiveSuiteFile(netarchiveSuiteFileName); // check secPolicyFileName and retrieve the corresponding file initSecPolicyFile(secPolicyFileName); initSLF4JXmlFile(slf4jConfigFileName); // check database initDatabase(databaseFileName); // check and apply the test arguments initTestArguments(testArguments); // check reset arguments. initReset(resetArgument); // evaluates the config file initEvaluate(evaluateArgument, sourceEncoding); // check the archive database initArchiveDatabase(arcDbFileName); // check the external jar-files library folder. initJarFolder(jarFolderName); //initBundlerZip(Optional.ofNullable( // ap.getCommandLine().getOptionValue(Constants.ARG_DEFAULT_BUNDLER_ZIP))); initBundlerZip(ap.getCommandLine().getOptionValue(Constants.ARG_DEFAULT_BUNDLER_ZIP)); // Make the configuration based on the input data deployConfig = new DeployConfiguration(deployConfigFile, netarchiveSuiteFile, secPolicyFile, slf4jConfigFile, outputDir, dbFile, arcDbFile, resetDirectory, externalJarFolder, sourceEncoding, defaultBundlerZip); // Write the scripts, directories and everything deployConfig.write(); } catch (SecurityException e) { // This problem should only occur in tests -> thus not err message. System.out.println("SECURITY ERROR: "); e.printStackTrace(); } catch (Throwable e) { System.err.println("DEPLOY APPLICATION ERROR: "); e.printStackTrace(); } } /** * Checks the configuration file argument and retrieves the file. * * @param deployConfigFileName The configuration file argument. */ private static void initConfigFile(String deployConfigFileName) { // check whether deploy-config file name is given as argument if (deployConfigFileName == null) { System.err.print(Constants.MSG_ERROR_NO_CONFIG_FILE_ARG); System.out.println(); System.exit(1); } // check whether deploy-config file has correct extensions if (!deployConfigFileName.endsWith(Constants.EXTENSION_XML_FILES)) { System.err.print(Constants.MSG_ERROR_CONFIG_EXTENSION); System.out.println(); System.exit(1); } // get the file deployConfigFile = new File(deployConfigFileName); // check whether the deploy-config file exists. if (!deployConfigFile.exists()) { System.err.print(Constants.MSG_ERROR_NO_CONFIG_FILE_FOUND); System.out.println(); System.exit(1); } } /** * Checks the NetarchiveSuite file argument and retrieves the file. * * @param netarchiveSuiteFileName The NetarchiveSuite argument. */ private static void initNetarchiveSuiteFile(String netarchiveSuiteFileName) { // check whether NetarchiveSuite file name is given as argument if (netarchiveSuiteFileName == null) { System.err.print(Constants.MSG_ERROR_NO_NETARCHIVESUITE_FILE_ARG); System.out.println(); System.exit(1); } // check whether the NetarchiveSuite file has correct extensions if (!netarchiveSuiteFileName.endsWith(Constants.EXTENSION_ZIP_FILES)) { System.err.print(Constants.MSG_ERROR_NETARCHIVESUITE_EXTENSION); System.out.println(); System.exit(1); } // get the file netarchiveSuiteFile = new File(netarchiveSuiteFileName); // check whether the NetarchiveSuite file exists. if (!netarchiveSuiteFile.isFile()) { System.err.print(Constants.MSG_ERROR_NO_NETARCHIVESUITE_FILE_FOUND); System.out.println(); System.out.println("Couldn't find file: " + netarchiveSuiteFile.getAbsolutePath()); System.exit(1); } } /** * Checks the security policy file argument and retrieves the file. * * @param secPolicyFileName The security policy argument. */ private static void initSecPolicyFile(String secPolicyFileName) { // check whether security policy file name is given as argument if (secPolicyFileName == null) { System.err.print(Constants.MSG_ERROR_NO_SECURITY_FILE_ARG); System.out.println(); System.exit(1); } // check whether security policy file has correct extensions if (!secPolicyFileName.endsWith(Constants.EXTENSION_POLICY_FILES)) { System.err.print(Constants.MSG_ERROR_SECURITY_EXTENSION); System.out.println(); System.exit(1); } // get the file secPolicyFile = new File(secPolicyFileName); // check whether the security policy file exists. if (!secPolicyFile.exists()) { System.err.print(Constants.MSG_ERROR_NO_SECURITY_FILE_FOUND); System.out.println(); System.out.println("Couldn't find file: " + secPolicyFile.getAbsolutePath()); System.exit(1); } } /** * Checks the SLF4J config file argument and retrieves the file. * * @param slf4jXmlFileName The SLF4J config argument. */ private static void initSLF4JXmlFile(String slf4jXmlFileName) { // check whether SLF4J config file name is given as argument if (slf4jXmlFileName == null) { System.err.print(Constants.MSG_ERROR_NO_SLF4J_CONFIG_FILE_ARG); System.out.println(); System.exit(1); } // check whether the SLF4J xml file has correct extensions if (!slf4jXmlFileName.endsWith(Constants.EXTENSION_XML_FILES)) { System.err.print(Constants.MSG_ERROR_SLF4J_CONFIG_EXTENSION); System.out.println(); System.exit(1); } // get the file slf4jConfigFile = new File(slf4jXmlFileName); // check whether the SLF4J xml file exists. if (!slf4jConfigFile.exists()) { System.err.print(Constants.MSG_ERROR_NO_SLF4J_CONFIG_FILE_FOUND); System.out.println(); System.out.println("Couldn't find file: " + slf4jConfigFile.getAbsolutePath()); System.exit(1); } } /** * Checks the database argument (if any) for extension and existence. * * @param databaseFileName The name of the database file. */ private static void initDatabase(String databaseFileName) { dbFile = null; // check the extension on the database, if it is given as argument if (databaseFileName != null) { if (!databaseFileName.endsWith(Constants.EXTENSION_JAR_FILES) && !databaseFileName.endsWith(Constants.EXTENSION_ZIP_FILES)) { System.err.print(Constants.MSG_ERROR_DATABASE_EXTENSION); System.out.println(); System.exit(1); } // get the file dbFile = new File(databaseFileName); // check whether the database file exists. if (!dbFile.isFile()) { System.err.print(Constants.MSG_ERROR_NO_DATABASE_FILE_FOUND); System.out.println(); System.out.println("Couldn't find file: " + dbFile.getAbsolutePath()); System.exit(1); } } } /** * Checks the arguments for resetting the directory. Only the arguments 'y' or 'yes' resets the database directory. * Default is 'no'. * <p> * If another argument than 'y', 'yes', 'n' or 'no' is given, an warning is given. * * @param resetArgument The argument for resetting given. */ private static void initReset(String resetArgument) { if (resetArgument != null) { if (resetArgument.equalsIgnoreCase(Constants.YES_SHORT) || resetArgument.equalsIgnoreCase(Constants.YES_LONG)) { // if positive argument, then set to true. resetDirectory = true; } else if (resetArgument.equalsIgnoreCase(Constants.NO_SHORT) || resetArgument.equalsIgnoreCase(Constants.NO_LONG)) { // if negative argument, then set to false. resetDirectory = false; } else { // if wrong argument, notify and set to false. System.err.println(Constants.MSG_ERROR_RESET_ARGUMENT); resetDirectory = false; } } else { // if no arguments, then resetDirectory = false; } } /** * Checks the arguments for evaluating the config file. Only the arguments 'y' or 'yes' is accepted for evaluation. * Anything else (including argument set to null) does not evaluate the deployConfigFile. * * @param evaluateArgument The argument for evaluation. * @param encoding the encoding to use to read from the input file */ public static void initEvaluate(String evaluateArgument, String encoding) { // check if argument is given and it is acknowledgement ('y' or 'yes') if ((evaluateArgument != null) && (!evaluateArgument.isEmpty()) && (evaluateArgument.equalsIgnoreCase(Constants.YES_SHORT) || evaluateArgument.equalsIgnoreCase(Constants.YES_LONG))) { // if yes, then evaluate config file EvaluateConfigFile evf = new EvaluateConfigFile(deployConfigFile, encoding); evf.evaluate(); } } /** * Checks the argument for the archive database. * * @param arcDbFileName The path to the archive database. */ public static void initArchiveDatabase(String arcDbFileName) { arcDbFile = null; // check the extension on the database, if it is given as argument if (arcDbFileName != null) { if (!arcDbFileName.endsWith(Constants.EXTENSION_JAR_FILES) && !arcDbFileName.endsWith(Constants.EXTENSION_ZIP_FILES)) { System.err.print(Constants.MSG_ERROR_BPDB_EXTENSION); System.out.println(); System.exit(1); } // get the file arcDbFile = new File(arcDbFileName); // check whether the database file exists. if (!arcDbFile.isFile()) { System.err.print(Constants.MSG_ERROR_NO_BPDB_FILE_FOUND); System.out.println(); System.out.println("Couldn't find file: " + arcDbFile.getAbsolutePath()); System.exit(1); } } } /** * Checks the argument for the external jar-folder. * * @param folderName The path to the folder. Global path. */ public static void initJarFolder(String folderName) { externalJarFolder = null; if (folderName != null && !folderName.isEmpty()) { externalJarFolder = new File(folderName); if (!externalJarFolder.isDirectory()) { System.err.print(Constants.MSG_ERROR_NO_JAR_FOLDER); System.out.println(); System.out.println("Couldn't find directory: " + externalJarFolder.getAbsolutePath()); System.exit(1); } } } /** * Checks if the default bundler zip file exists if defined. * * @param defaultBundlerZipName The path to the default bundler zip file to use. */ public static void initBundlerZip(String defaultBundlerZipName) { if (defaultBundlerZipName != null) { defaultBundlerZip = new File(defaultBundlerZipName); if (!defaultBundlerZip.exists()) { System.err.print(Constants.MSG_ERROR_NO_BUNDLER_ZIP_FILE); System.out.println(); System.out .println("Couldn't find the default bundler file: " + defaultBundlerZip.getAbsolutePath()); System.exit(1); } } else { defaultBundlerZip = null; } } /** * Applies the test arguments. * <p> * If the test arguments are given correctly, the configuration file is loaded and changed appropriately, then * written to a test configuration file. * <p> * The new test configuration file has the same name as the original configuration file, except ".xml" is replaced * by "_text.xml". Thus "path/config.xml" -> "path/config_test.xml". * * @param testArguments The test arguments. */ private static void initTestArguments(String testArguments) { // test if any test arguments (if none, don't apply, just stop). if (testArguments == null || testArguments.isEmpty()) { return; } String[] changes = testArguments.split(Constants.REGEX_COMMA_CHARACTER); if (changes.length != Constants.TEST_ARGUMENTS_REQUIRED) { System.err.print(Constants.MSG_ERROR_TEST_ARGUMENTS); System.out.println(); System.out.println(changes.length + " arguments was given and " + Constants.TEST_ARGUMENTS_REQUIRED + " was expected."); System.out.println("Received: " + testArguments); System.exit(1); } try { CreateTestInstance cti = new CreateTestInstance(deployConfigFile); // apply the arguments cti.applyTestArguments(changes[Constants.TEST_ARGUMENT_OFFSET_INDEX], changes[Constants.TEST_ARGUMENT_HTTP_INDEX], changes[Constants.TEST_ARGUMENT_ENVIRONMENT_NAME_INDEX], changes[Constants.TEST_ARGUMENT_MAIL_INDEX]); // replace ".xml" with "_test.xml" String tmp = deployConfigFile.getPath(); // split this into two ("path/config.xml" = {"path/config", ".xml"}) String[] configFile = tmp.split(Constants.REGEX_DOT_CHARACTER); // take the first part and add test ending // ("path/config" + "_test.xml" = "path/config_test.xml") String nameOfNewConfig = configFile[0] + Constants.TEST_CONFIG_FILE_REPLACE_ENDING; // create and use new config file. cti.createConfigurationFile(nameOfNewConfig); deployConfigFile = new File(nameOfNewConfig); } catch (IOException e) { System.out.println("Error in test arguments: " + e); System.exit(1); } } /** * Handles the incoming arguments. */ private static class ArgumentParameters { /** Options object for parameters. */ private Options options = new Options(); /** Parser for parsing the command line arguments. */ private CommandLineParser parser = new PosixParser(); /** The command line. */ private CommandLine cmd; /** Whether the options has an argument. */ private static final boolean HAS_ARG = true; /** * Initialise options by setting legal parameters for batch jobs. */ ArgumentParameters() { options.addOption(Constants.ARG_CONFIG_FILE, HAS_ARG, "Config file."); options.addOption(Constants.ARG_NETARCHIVE_SUITE_FILE, HAS_ARG, "The NetarchiveSuite package file."); options.addOption(Constants.ARG_SECURITY_FILE, HAS_ARG, "Security property file."); options.addOption(Constants.ARG_SLF4J_CONFIG_FILE, HAS_ARG, "SLF4J config file."); options.addOption(Constants.ARG_OUTPUT_DIRECTORY, HAS_ARG, "[OPTIONAL] output directory."); options.addOption(Constants.ARG_DATABASE_FILE, HAS_ARG, "[OPTIONAL] Database file."); options.addOption(Constants.ARG_TEST, HAS_ARG, "[OPTIONAL] Tests arguments (offset for http port," + " http port, environment name, mail receiver)."); options.addOption(Constants.ARG_RESET, HAS_ARG, "[OPTIONAL] Reset temp directory ('y' or 'yes'" + "means reset, anything else means do not reset." + " Different from 'y', 'yes', 'n' or 'no' gives" + " an error message."); options.addOption(Constants.ARG_EVALUATE, HAS_ARG, "[OPTIONAL] Evaluate the config file."); options.addOption(Constants.ARG_ARC_DB, HAS_ARG, "[OPTIONAL] The archive database file"); options.addOption(Constants.ARG_JAR_FOLDER, HAS_ARG, "[OPTIONAL] Installing the external jar library " + "files within the given folder."); options.addOption(Constants.ARG_SOURCE_ENCODING, HAS_ARG, "[OPTIONAL] Encoding to use for source files."); options.addOption(Constants.ARG_DEFAULT_BUNDLER_ZIP, HAS_ARG, "[OPTIONAL] The bundled harvester to use. " + "If not provided here the bundler needs to be provided in the settings for each (H3) harvester"); } /** * Parsing the input arguments. * * @param args The input arguments. * @return Whether it parsed correctly or not. */ Boolean parseParameters(String[] args) { try { // parse the command line arguments cmd = parser.parse(options, args); } catch (ParseException exp) { System.out.println("Parsing error: " + exp); return false; } return true; } /** * Get the list of possible arguments with their description. * * @return The list describing the possible arguments. */ String listArguments() { StringBuilder res = new StringBuilder(); res.append(Constants.NEWLINE); res.append(Constants.INIT_ARGUMENTS_LIST); // add options for (Object o : options.getOptions()) { Option op = (Option) o; res.append(Constants.NEWLINE); res.append(Constants.DASH); res.append(op.getOpt()); res.append(Constants.SPACE); res.append(op.getDescription()); } return res.toString(); } /** * For retrieving the options. * * @return The options. */ public Options getOptions() { return options; } /** * For retrieving the commandLine. * * @return The cmd. */ public CommandLine getCommandLine() { return cmd; } } }