dk.netarkivet.deploy.EvaluateConfigFile.java Source code

Java tutorial

Introduction

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

Source

/* $Id$
 * $Revision$
 * $Date$
 * $Author$
 *
 * The Netarchive Suite - Software to harvest and preserve websites
 * Copyright 2004-2012 The Royal Danish Library, the Danish State and
 * University Library, the National Library of France and the Austrian
 * National Library.
 *
 * This library 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 library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 *   USA
 */
package dk.netarkivet.deploy;

import java.io.File;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

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 final Log log = LogFactory.getLog(getClass().getName());

    /**
     * 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) {
            String msg = "Error occured during evaluation: " + e;
            System.err.println(msg);
            log.trace(msg);
        }
    }

    /**
     * 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) {
            String errMsg = "Cannot handle complete settings file.";
            log.error(errMsg, e);
            throw new IOFailure(errMsg, 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++;
        }

        for (i++; i < elList.length; i++) {
            res.append(elList[i]);
            res.append(Constants.SLASH);
        }

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

        return res.toString();
    }
}