org.ebayopensource.turmeric.runtime.config.validation.AbstractVerifier.java Source code

Java tutorial

Introduction

Here is the source code for org.ebayopensource.turmeric.runtime.config.validation.AbstractVerifier.java

Source

/*******************************************************************************
 * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *******************************************************************************/
package org.ebayopensource.turmeric.runtime.config.validation;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;

import org.apache.commons.lang.StringUtils;
import org.jaxen.JaxenException;
import org.jaxen.XPath;
import org.jaxen.jdom.JDOMXPath;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.Text;
import org.jdom.input.JDOMParseException;
import org.jdom.input.SAXBuilder;

public abstract class AbstractVerifier {
    private static final Logger LOG = Logger.getLogger(AbstractVerifier.class.getName());
    protected Report report;
    protected List<String> excludedClasses;
    private List<String> excludedConfigs;
    private PathRegex pathregex;

    protected String asArrayString(List<String> entries) {
        StringBuilder str = new StringBuilder();
        str.append("[");
        boolean delim = false;
        for (String entry : entries) {
            if (delim) {
                str.append(", ");
            }
            str.append(entry);
            delim = true;
        }
        str.append("]");
        return str.toString();
    }

    protected void assertClassExists(File hit, Document doc, String xpath) {
        try {
            Namespace ns = doc.getRootElement().getNamespace();
            XPath expr = new JDOMXPath(xpath);
            expr.addNamespace("c", ns.getURI());

            List<?> nodes = expr.selectNodes(doc);
            LOG.fine("Searching for: " + xpath);
            for (Object node : nodes) {
                String classname = null;
                if (node instanceof Text) {
                    Text txt = (Text) node;
                    classname = txt.getTextNormalize();
                    assertClassExists(hit, txt.getParentElement(), classname);
                    continue;
                }

                if (node instanceof Element) {
                    Element elem = (Element) node;
                    classname = elem.getAttributeValue("class");
                    if (StringUtils.isBlank(classname)) {
                        classname = elem.getAttributeValue("class-name");
                    }
                    assertClassExists(hit, elem, classname);
                    continue;
                }
                LOG.fine("Found: " + node);
            }
        } catch (JaxenException e) {
            LOG.log(Level.WARNING, "Unable to apply xpath: " + xpath, e);
        }
    }

    protected void assertClassExists(File hit, Element elemContext, String classname) {
        LOG.fine("Found Text/ClassName: " + classname);
        if (isExcludedClasses(classname)) {
            return; // skip, excluded
        }
        if (!doesClassExists(classname)) {
            String context = calculateXpathRefish(elemContext);
            report.violation(context, "Class not found: %s", classname);
        }
    }

    private boolean isExcludedClasses(String classname) {
        if (this.excludedClasses == null) {
            return false;
        }
        return this.excludedClasses.contains(classname);
    }

    public void setBaseDir(File dir) {
        this.pathregex = new PathRegex(dir, getFileRegex());
    }

    public final void verifyAllConfigMatches() {
        List<File> hits = FileFinder.findFileMatches(pathregex);
        for (File hit : hits) {
            verifyFile(hit);
        }
    }

    public void verifyFile(File file) {
        try {
            report.fileStart(file);
            String relpath = this.pathregex.getRelativePath(file);
            if (isExcludedConfigs(relpath)) {
                return; // skip. excluded config
            }
            if (file.length() <= 0) {
                return; // skip. empty file
            }
            verifyHit(file);
        } finally {
            report.fileEnd();
        }
    }

    private boolean isExcludedConfigs(String relpath) {
        if (this.excludedConfigs == null) {
            return false;
        }
        return this.excludedConfigs.contains(relpath);
    }

    protected String calculateXpathRefish(Element elem) {
        Stack<String> ref = new Stack<String>();
        String name;
        Element p, e = elem;
        while (e != null) {
            name = e.getName();
            p = e.getParentElement();
            if (p != null) {
                name = getXmlElementRefName(e, p);
            }
            ref.push(name);
            e = p;
        }
        StringBuilder refish = new StringBuilder();
        refish.append("/");
        while (!ref.empty()) {
            refish.append("/").append(ref.pop());
        }
        return refish.toString();
    }

    private String getXmlElementRefName(Element e, Element p) {
        String name = e.getName();

        String attrid = e.getAttributeValue("id");
        if (StringUtils.isNotBlank(attrid)) {
            return name + "[@id='" + attrid + "']";
        }

        String attrname = e.getAttributeValue("name");
        if (StringUtils.isNotBlank(attrname)) {
            return name + "[@name='" + attrname + "']";
        }

        int idx = p.indexOf(e);
        if (idx >= 0) {
            name += "[" + idx + "]";
        }

        return name;
    }

    protected boolean doesClassExists(String classname) {
        try {
            Class.forName(classname, false, Thread.currentThread().getContextClassLoader());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public List<String> getExcludedClasses() {
        return excludedClasses;
    }

    public List<String> getExcludedConfigs() {
        return excludedConfigs;
    }

    public abstract String getFileRegex();

    protected Matcher getHitRegexMatcher(File hit) {
        return this.pathregex.getMatcher(hit);
    }

    public Report getReport() {
        return report;
    }

    public void setReport(Report report) {
        this.report = report;
    }

    public void setExcludedClasses(List<String> excludedClasses) {
        this.excludedClasses = excludedClasses;
    }

    public void setExcludedConfigs(List<String> excludedConfigs) {
        this.excludedConfigs = excludedConfigs;
    }

    public abstract void verifyHit(File hit);

    public Document xmlParse(File xmlFile) throws JDOMException, IOException {
        try {
            SAXBuilder builder = new SAXBuilder(false);
            return builder.build(xmlFile);
        } catch (JDOMParseException e) {
            report.violation(Integer.toString(e.getLineNumber()), "XML Parse Violation: %s", e.getMessage());
            throw e;
        }
    }

    protected boolean validRootElement(File hit, Document doc, String expectedRootName) {
        Element root = doc.getRootElement();

        if (!expectedRootName.equals(root.getName())) {
            report.violation("Root XML element", "Must have root element of <%s/> but found <%s/>",
                    expectedRootName, root.getName());
            return false; // can't work with this XML :-(
        }

        return true;
    }

    protected boolean validRootElement(File hit, Document doc, String expectedRootName,
            String expectedDefaultNamespace) {
        Element root = doc.getRootElement();

        if (!expectedRootName.equals(root.getName())) {
            report.violation("Root XML element", "Must have root element of <%s/> but found <%s/>",
                    expectedRootName, root.getName());
            return false; // can't work with this XML :-(
        }

        String actualNamespace = root.getNamespaceURI();

        if (StringUtils.isBlank(actualNamespace)) {
            report.violation("Default Namespace",
                    "Must have the default namespace declaration of <%s xmlns=\"%s\"/>, but found none",
                    expectedRootName, expectedDefaultNamespace);
            return false; // can't work with this XML :-(
        } else if (!expectedDefaultNamespace.equals(actualNamespace)) {
            report.violation("Default Namespace",
                    "Expected default namespace declaration <%s xmlns=\"%s\"> but actually found <%s xmlns=\"%s\"/>",
                    expectedRootName, expectedDefaultNamespace, root.getName(), actualNamespace);
            // while invalid, this doesn't prevent the rest of the tests from proceeding.
        }

        return true;
    }
}