dk.netarkivet.deploy.EvaluateConfigFile.java Source code

Java tutorial

Introduction

Here is the source code for dk.netarkivet.deploy.EvaluateConfigFile.java

Source

/*
 * #%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.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import dk.netarkivet.common.exceptions.ArgumentNotValid;
import dk.netarkivet.common.exceptions.IOFailure;
import dk.netarkivet.common.utils.FileUtils;

/**
 * Class for evaluating a config file. Tests the settings in the config file against default settings to test for
 * wrongly assigned elements.
 */
public class EvaluateConfigFile {

    /** The elements to check the settings against. */
    private Element completeSettings;
    /** The root element in the xml tree. */
    private XmlStructure root;
    /** the log, for logging stuff instead of displaying them directly. */
    private static final Logger log = LoggerFactory.getLogger(EvaluateConfigFile.class);

    /**
     * Constructor. Only initialises the config file and settings list.
     *
     * @param deployConfigFile The file to evaluate.
     * @param encoding the encoding to use to read from file
     */
    public EvaluateConfigFile(File deployConfigFile, String encoding) {
        ArgumentNotValid.checkNotNull(deployConfigFile, "File deployConfigFile");
        initLoadDefaultSettings();
        root = new XmlStructure(deployConfigFile, encoding);
    }

    /**
     * Evaluates the config file. This is done by evaluating the settings branch for all the instances in the XML-tree
     * (global, physical locaiton, machine and application)
     */
    @SuppressWarnings("unchecked")
    public void evaluate() {
        try {
            // check global settings
            evaluateElement(root.getChild(Constants.COMPLETE_SETTINGS_BRANCH));
            List<Element> physLocs = root.getChildren(Constants.DEPLOY_PHYSICAL_LOCATION);
            for (Element pl : physLocs) {
                // check physical location settings
                evaluateElement(pl.element(Constants.COMPLETE_SETTINGS_BRANCH));
                List<Element> macs = pl.elements(Constants.DEPLOY_MACHINE);
                for (Element mac : macs) {
                    // check machine settings
                    evaluateElement(mac.element(Constants.COMPLETE_SETTINGS_BRANCH));
                    List<Element> apps = mac.elements(Constants.DEPLOY_APPLICATION_NAME);
                    for (Element app : apps) {
                        // check application settings
                        evaluateElement(app.element(Constants.COMPLETE_SETTINGS_BRANCH));
                    }
                }
            }
        } catch (Exception e) {
            log.error("Error occured during evaluation: ", e);
        }
    }

    /**
     * Load the default settings files as reference trees. These are used for testing whether the branches in the
     * settings file are to be used or not.
     */
    private void initLoadDefaultSettings() {
        File f = FileUtils.getResourceFileFromClassPath(Constants.BUILD_COMPLETE_SETTINGS_FILE_PATH);
        try {
            Document doc;
            SAXReader reader = new SAXReader();
            if (f.canRead()) {
                doc = reader.read(f);
                completeSettings = doc.getRootElement();
            } else {
                log.warn("Cannot read file: '{}'", f.getAbsolutePath());
            }
        } catch (DocumentException e) {
            log.error("Cannot handle complete settings file.", e);
            throw new IOFailure("Cannot handle complete settings file.", e);
        }
    }

    /**
     * Evaluates a element (has to called with the settings branch). Then tries to evaluate all the branches to the
     * element. The method is called recursively for the children of curElem.
     *
     * @param curElem The current element to evaluate. Null element represents in this context that no settings branch
     * exists for the current instance.
     */
    @SuppressWarnings("unchecked")
    private void evaluateElement(Element curElem) {
        // make sure to catch null-pointers
        if (curElem == null) {
            return;
        }
        List<Element> elList = curElem.elements();
        for (Element el : elList) {
            boolean valid = false;
            // get path
            String path = getSettingsPath(el);

            // check if path exists in any default setting.
            valid = existBranch(completeSettings, path.split(Constants.SLASH));

            if (valid) {
                if (!el.isTextOnly()) {
                    evaluateElement(el);
                }
            } else {
                // Print out the 'illegal' branches.
                System.out.println("Branch in settings not found: " + path.replace(Constants.SLASH, Constants.DOT));
            }
        }
    }

    /**
     * For testing whether a branch with the current path exists.
     *
     * @param settings The root of the default settings XML-tree.
     * @param path The path to the branch to test.
     * @return Whether the branch at the end of the path in the root exists.
     */
    private boolean existBranch(Element settings, String[] path) {
        Element curE = settings;
        for (String st : path) {
            if (curE == null) {
                return false;
            }
            curE = curE.element(st);
        }

        // return whether the final branch exists.
        return (curE != null);
    }

    /**
     * Gets the path from settings of an element.
     *
     * @param el The element to get the settings path.
     * @return The path from settings to the element, in the XML-tree.
     */
    private String getSettingsPath(Element el) {
        String[] elList = el.getPath().split(Constants.SLASH);

        StringBuilder res = new StringBuilder();
        int i = 0;
        // find the index for settings
        while (i < elList.length && !elList[i].equalsIgnoreCase(Constants.COMPLETE_SETTINGS_BRANCH)) {
            ++i;
        }

        // TODO WTF?!
        for (i++; i < elList.length; i++) {
            res.append(elList[i]);
            res.append(Constants.SLASH);
        }

        // remove last '/'
        res.deleteCharAt(res.length() - 1);

        return res.toString();
    }

}