001/*
002 * #%L
003 * Netarchivesuite - deploy
004 * %%
005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University 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.IOException;
027import java.util.ArrayList;
028import java.util.List;
029//import java.util.Optional;
030
031import org.dom4j.Element;
032
033import dk.netarkivet.common.exceptions.ArgumentNotValid;
034import dk.netarkivet.common.exceptions.IOFailure;
035import dk.netarkivet.common.utils.FileUtils;
036
037/**
038 * The structure for the deploy-config. Loads the deploy-configuration from an XML file into a XmlStructure.
039 */
040public class DeployConfiguration {
041
042    /** The configuration structure (deployGlobal). */
043    private XmlStructure config;
044    /** The settings branch of the config. */
045    private XmlStructure settings;
046    /** The parameters for running java. */
047    private Parameters machineParam;
048    /** The list of the physical locations. */
049    private List<PhysicalLocation> physLocs;
050    /** The file containing the deploy-configuration. */
051    private File deployConfigFile;
052    /** The NetarchiveSuite file (in .zip). */
053    private File netarchiveSuiteFile;
054    /** The security policy file. */
055    private File secPolicyFile;
056     /** The SLF4J config file. */
057    private File slf4jConfigFile;
058    /** The directory for output. */
059    private File outputDir;
060    /** The name of the database. */
061    private File databaseFileName;
062    /** The name of the archive database. */
063    private File arcDatabaseFileName;
064    /** The optional choice for resetting tempDir. */
065    private boolean resetDirectory;
066    /** The folder containing the external jar library files. */
067    private File jarFolder;
068    //private final Optional<File> defaultBundlerZip;
069    private final File defaultBundlerZip;
070
071    /**
072     * Constructor. Initialise everything.
073     *
074     * @param deployConfigFileName Name of configuration file.
075     * @param netarchiveSuiteFileName Name of installation file.
076     * @param secPolicyFileName Name of security policy file.
077     * @param outputDirName Directory for the output.
078     * @param dbFileName Name of the database.
079     * @param arcdbFileName The name of the archive database.
080     * @param resetDir Whether the temporary directory should be reset.
081     * @param externalJarFolder The folder containing the external jar library files.
082     * @param sourceEncoding the encoding to use to read input files
083     * @throws ArgumentNotValid If one of the following arguments is null: deployConfigFileName netarchiveSuiteFileName,
084     * secPolicyFileName, logPropFileName.
085     */
086    public DeployConfiguration(
087            File deployConfigFileName,
088            File netarchiveSuiteFileName,
089            File secPolicyFileName,
090            File slf4jConfigFileName,
091            String outputDirName,
092            File dbFileName,
093            File arcdbFileName,
094            boolean resetDir,
095            File externalJarFolder,
096            String sourceEncoding,
097            //Optional<File defaultBundlerZip
098            File defaultBundlerZip)
099            throws ArgumentNotValid {
100        ArgumentNotValid.checkNotNull(deployConfigFileName, "No config file");
101        ArgumentNotValid.checkNotNull(netarchiveSuiteFileName, "No installation file");
102        ArgumentNotValid.checkNotNull(secPolicyFileName, "No security file");
103        // ArgumentNotValid.checkNotNull(slf4jConfigFileName, "No slf4jConfigFileName file");
104
105        deployConfigFile = deployConfigFileName;
106        netarchiveSuiteFile = netarchiveSuiteFileName;
107        secPolicyFile = secPolicyFileName;
108        slf4jConfigFile = slf4jConfigFileName;
109        databaseFileName = dbFileName;
110        arcDatabaseFileName = arcdbFileName;
111        resetDirectory = resetDir;
112        jarFolder = externalJarFolder;
113        this.defaultBundlerZip = defaultBundlerZip;
114
115        // get configuration tree, settings and parameters
116        config = new XmlStructure(deployConfigFile, sourceEncoding);
117        settings = new XmlStructure(config.getChild(Constants.COMPLETE_SETTINGS_BRANCH));
118        machineParam = new Parameters(config);
119
120        String environmentName = config.getSubChildValue(Constants.COMPLETE_ENVIRONMENT_NAME_LEAF);
121
122        // validate the environment name.
123        if (!Constants.validEnvironmentName(environmentName)) {
124            System.err.print(Constants.MSG_ERROR_INVALID_ENVIRONMENT_NAME + environmentName);
125            System.out.println();
126            System.exit(1);
127        }
128
129        // if a outputDir has not been given as argument,
130        // it is the output directory
131        if (outputDirName == null) {
132            // Load output directory from config file
133            outputDirName = Constants.DOT + Constants.SLASH + environmentName + Constants.SLASH;
134        }
135        outputDir = new File(outputDirName);
136        // make sure that directory outputDir exists
137        FileUtils.createDir(outputDir);
138        extractElements();
139
140        copyNetarchiveSuiteFile();
141    }
142
143    /**
144     * Extracts the physical locations and put them into the list.
145     */
146    private void extractElements() {
147        // initialise physical location array
148        physLocs = new ArrayList<PhysicalLocation>();
149        // get the list from the XML tree
150        List<Element> physList = config.getChildren(Constants.DEPLOY_PHYSICAL_LOCATION);
151        // get all physical locations into the list
152        for (Element elem : physList) {
153            physLocs.add(new PhysicalLocation(elem, settings, machineParam, netarchiveSuiteFile.getName(),
154                    slf4jConfigFile, secPolicyFile, databaseFileName, arcDatabaseFileName, resetDirectory, jarFolder,
155                    this));
156        }
157    }
158
159    /**
160     * Method for copying the NetarchiveSuite file to output directory. This handles the following three scenarios:
161     * <p>
162     * <ol>
163     * <li>outputDir == directory of zip file</li>
164     * Do nothing. <br>
165     * <li>outputDir != directory of zip file, but another zip file with same name exists in the directory</li>
166     * Remove the existing file before copy of the given file. <br>
167     * <li>outputDir != directory of zip file and no other zip file</li>
168     * Copy file to output directory.
169     * </ol>
170     */
171    private void copyNetarchiveSuiteFile() {
172        // initialise the new file. This should have the same name
173        // as the original file, but be placed in the output directory.
174        File newNetarchiveSuiteFile = new File(outputDir, netarchiveSuiteFile.getName());
175        try {
176
177            // check first scenario
178            if (newNetarchiveSuiteFile.getCanonicalPath().equals(netarchiveSuiteFile.getCanonicalPath())) {
179                // thus first scenario is true, and nothing should be done.
180                return;
181            }
182
183            // If the file exists = second scenario, and thus issue warning and
184            // delete file before the given netarchiveSuiteFile is copied.
185            if (newNetarchiveSuiteFile.exists()) {
186                // issue warning
187                System.out.println(Constants.MSG_WARN_ZIPFILE_ALREADY_EXISTS
188                        + newNetarchiveSuiteFile.getCanonicalPath());
189                newNetarchiveSuiteFile.delete();
190            }
191
192            // copy the file.
193            FileUtils.copyFile(netarchiveSuiteFile, newNetarchiveSuiteFile);
194        } catch (IOException e) {
195            // handle IOExceptions
196            System.out.println(Constants.MSG_ERROR_ZIP_CANNONICAL_PATH + netarchiveSuiteFile.getAbsolutePath());
197            e.printStackTrace();
198            System.exit(1);
199        } catch (IOFailure e1) {
200            // handle a IOFailure, can only be thrown by FileUtils.copyFile
201            System.out.println("Unable to copy file '" + netarchiveSuiteFile.getAbsolutePath()
202                    + "' to the destination '" + newNetarchiveSuiteFile.getAbsolutePath() + "'.");
203            e1.printStackTrace();
204            System.exit(1);
205        }
206    }
207
208    /**
209     * Makes every physical location create their scripts.
210     */
211    public void write() {
212        // write all physical locations
213        for (PhysicalLocation pl : physLocs) {
214            pl.write(outputDir);
215        }
216    }
217
218    /**
219     * @return The default harvester bundler zip file to use deploy to the relevant harvesters.
220     */
221    //public Optional<File> getDefaultBundlerZip() {
222    //    return defaultBundlerZip;
223    //}
224    public File getDefaultBundlerZip() {
225        return defaultBundlerZip;
226    }
227}