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.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    /** The optional choice for a logo png file */
071    private File logoFile;
072    /** The optional choice for a menulogo png file */
073    private File menulogoFile;
074    /** The folder containing the bitmagasin configuration files. */
075    private File bitmagDir;
076
077    /**
078     * Constructor. Initialise everything.
079     *
080     * @param deployConfigFileName Name of configuration file.
081     * @param netarchiveSuiteFileName Name of installation file.
082     * @param secPolicyFileName Name of security policy file.
083     * @param outputDirName Directory for the output.
084     * @param dbFileName Name of the database.
085     * @param arcdbFileName The name of the archive database.
086     * @param resetDir Whether the temporary directory should be reset.
087     * @param externalJarFolder The folder containing the external jar library files.
088     * @param sourceEncoding the encoding to use to read input files
089     * @throws ArgumentNotValid If one of the following arguments is null: deployConfigFileName netarchiveSuiteFileName,
090     * secPolicyFileName, logPropFileName.
091     */
092    public DeployConfiguration(
093            File deployConfigFileName,
094            File netarchiveSuiteFileName,
095            File secPolicyFileName,
096            File slf4jConfigFileName,
097            String outputDirName,
098            File dbFileName,
099            File arcdbFileName,
100            boolean resetDir,
101            File externalJarFolder,
102            String sourceEncoding,
103            //Optional<File defaultBundlerZip
104            File defaultBundlerZip,
105            File logoFile,
106            File menulogoFile,
107            File bitmagSourceDir)
108            throws ArgumentNotValid {
109        ArgumentNotValid.checkNotNull(deployConfigFileName, "No config file");
110        ArgumentNotValid.checkNotNull(netarchiveSuiteFileName, "No installation file");
111        ArgumentNotValid.checkNotNull(secPolicyFileName, "No security file");
112        // ArgumentNotValid.checkNotNull(slf4jConfigFileName, "No slf4jConfigFileName file");
113
114        deployConfigFile = deployConfigFileName;
115        netarchiveSuiteFile = netarchiveSuiteFileName;
116        secPolicyFile = secPolicyFileName;
117        slf4jConfigFile = slf4jConfigFileName;
118        databaseFileName = dbFileName;
119        arcDatabaseFileName = arcdbFileName;
120        resetDirectory = resetDir;
121        jarFolder = externalJarFolder;
122        bitmagDir = bitmagSourceDir;
123        this.defaultBundlerZip = defaultBundlerZip;
124        this.logoFile = logoFile;
125        this.menulogoFile = menulogoFile;
126
127        // get configuration tree, settings and parameters
128        config = new XmlStructure(deployConfigFile, sourceEncoding);
129        settings = new XmlStructure(config.getChild(Constants.COMPLETE_SETTINGS_BRANCH));
130        machineParam = new Parameters(config);
131
132        String environmentName = config.getSubChildValue(Constants.COMPLETE_ENVIRONMENT_NAME_LEAF);
133
134        // validate the environment name.
135        if (!Constants.validEnvironmentName(environmentName)) {
136            System.err.print(Constants.MSG_ERROR_INVALID_ENVIRONMENT_NAME + environmentName);
137            System.out.println();
138            System.exit(1);
139        }
140
141        // if a outputDir has not been given as argument,
142        // it is the output directory
143        if (outputDirName == null) {
144            // Load output directory from config file
145            outputDirName = Constants.DOT + Constants.SLASH + environmentName + Constants.SLASH;
146        }
147        outputDir = new File(outputDirName);
148        // make sure that directory outputDir exists
149        FileUtils.createDir(outputDir);
150        extractElements();
151
152        copyNetarchiveSuiteFile();
153    }
154
155    /**
156     * Extracts the physical locations and put them into the list.
157     */
158    private void extractElements() {
159        // initialise physical location array
160        physLocs = new ArrayList<PhysicalLocation>();
161        // get the list from the XML tree
162        List<Element> physList = config.getChildren(Constants.DEPLOY_PHYSICAL_LOCATION);
163        // get all physical locations into the list
164        for (Element elem : physList) {
165            physLocs.add(new PhysicalLocation(elem, settings, machineParam, netarchiveSuiteFile.getName(),
166                    slf4jConfigFile, secPolicyFile, databaseFileName, arcDatabaseFileName, resetDirectory, jarFolder,
167                    logoFile, menulogoFile, bitmagDir, this));
168        }
169    }
170
171    /**
172     * Method for copying the NetarchiveSuite file to output directory. This handles the following three scenarios:
173     * <p>
174     * <ol>
175     * <li>outputDir == directory of zip file</li>
176     * Do nothing. <br>
177     * <li>outputDir != directory of zip file, but another zip file with same name exists in the directory</li>
178     * Remove the existing file before copy of the given file. <br>
179     * <li>outputDir != directory of zip file and no other zip file</li>
180     * Copy file to output directory.
181     * </ol>
182     */
183    private void copyNetarchiveSuiteFile() {
184        // initialise the new file. This should have the same name
185        // as the original file, but be placed in the output directory.
186        File newNetarchiveSuiteFile = new File(outputDir, netarchiveSuiteFile.getName());
187        try {
188
189            // check first scenario
190            if (newNetarchiveSuiteFile.getCanonicalPath().equals(netarchiveSuiteFile.getCanonicalPath())) {
191                // thus first scenario is true, and nothing should be done.
192                return;
193            }
194
195            // If the file exists = second scenario, and thus issue warning and
196            // delete file before the given netarchiveSuiteFile is copied.
197            if (newNetarchiveSuiteFile.exists()) {
198                // issue warning
199                System.out.println(Constants.MSG_WARN_ZIPFILE_ALREADY_EXISTS
200                        + newNetarchiveSuiteFile.getCanonicalPath());
201                newNetarchiveSuiteFile.delete();
202            }
203
204            // copy the file.
205            FileUtils.copyFile(netarchiveSuiteFile, newNetarchiveSuiteFile);
206        } catch (IOException e) {
207            // handle IOExceptions
208            System.out.println(Constants.MSG_ERROR_ZIP_CANNONICAL_PATH + netarchiveSuiteFile.getAbsolutePath());
209            e.printStackTrace();
210            System.exit(1);
211        } catch (IOFailure e1) {
212            // handle a IOFailure, can only be thrown by FileUtils.copyFile
213            System.out.println("Unable to copy file '" + netarchiveSuiteFile.getAbsolutePath()
214                    + "' to the destination '" + newNetarchiveSuiteFile.getAbsolutePath() + "'.");
215            e1.printStackTrace();
216            System.exit(1);
217        }
218    }
219
220    /**
221     * Makes every physical location create their scripts.
222     */
223    public void write() {
224        // write all physical locations
225        for (PhysicalLocation pl : physLocs) {
226            pl.write(outputDir);
227        }
228    }
229
230    /**
231     * @return The default harvester bundler zip file to use deploy to the relevant harvesters.
232     */
233    //public Optional<File> getDefaultBundlerZip() {
234    //    return defaultBundlerZip;
235    //}
236    public File getDefaultBundlerZip() {
237        return defaultBundlerZip;
238    }
239}