org.pustefixframework.maven.plugins.ModuleDescriptor.java Source code

Java tutorial

Introduction

Here is the source code for org.pustefixframework.maven.plugins.ModuleDescriptor.java

Source

/*
 * This file is part of Pustefix.
 *
 * Pustefix 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 of the License, or
 * (at your option) any later version.
 *
 * Pustefix 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 Pustefix; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package org.pustefixframework.maven.plugins;

import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.maven.plugin.logging.Log;
import org.springframework.util.AntPathMatcher;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Holds information about a module read from the module descriptor file.
 *
 */
public class ModuleDescriptor {

    private final static String NS_MODULE_DESCRIPTOR = "http://www.pustefix-framework.org/2008/namespace/module-descriptor";

    final static String DEFAULT_RESOURCE_PATH = "/PUSTEFIX-INF";

    private URL url;
    private String name;
    private String resourcePath = DEFAULT_RESOURCE_PATH;
    private boolean contentEditable;
    private Map<String, Set<String>> moduleToResourcePaths = new HashMap<String, Set<String>>();
    private Map<String, Set<String>> moduleToResourcePathPatterns = new HashMap<String, Set<String>>();
    private Dictionary<String, String> moduleOverrideFilterAttributes = new Hashtable<String, String>();
    private Dictionary<String, String> defaultSearchFilterAttributes = new Hashtable<String, String>();
    private boolean defaultSearchable;
    private int defaultSearchPriority = 10;
    private List<String> staticPaths = new ArrayList<String>();
    private Set<String> i18nPaths = new HashSet<String>();

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    private ModuleDescriptor(URL url, String name) {
        this.url = url;
        this.name = name;
    }

    public URL getURL() {
        return url;
    }

    public String getName() {
        return name;
    }

    public String getResourcePath() {
        return resourcePath;
    }

    public void setResourcePath(String resourcePath) {
        this.resourcePath = resourcePath;
    }

    public boolean isContentEditable() {
        return contentEditable;
    }

    public void setContentEditable(boolean contentEditable) {
        this.contentEditable = contentEditable;
    }

    /**
     * Adds resource/module overridden by this module.
     * 
     * @param module - Module name
     * @param resourcePath - Resource path (either the full path or an ant-style pattern)
     */
    public void addOverridedResource(String module, String resourcePath) {
        if (resourcePath.contains("?") || resourcePath.contains("*")) {
            Set<String> resList = moduleToResourcePathPatterns.get(module);
            if (resList == null) {
                resList = new HashSet<String>();
                moduleToResourcePathPatterns.put(module, resList);
            }
            resList.add(resourcePath);
        } else {
            Set<String> resList = moduleToResourcePaths.get(module);
            if (resList == null) {
                resList = new HashSet<String>();
                moduleToResourcePaths.put(module, resList);
            }
            resList.add(resourcePath);
        }
    }

    public boolean overridesResource(String module, String path) {
        Set<String> overrides = moduleToResourcePaths.get(module);
        if (overrides != null) {
            if (overrides.contains(path))
                return true;
        }
        overrides = moduleToResourcePathPatterns.get(module);
        if (overrides != null) {
            for (String pattern : overrides) {
                if (antPathMatcher.match(pattern, path))
                    return true;
            }
        }
        return false;
    }

    public void addModuleOverrideFilterAttribute(String name, String value) {
        moduleOverrideFilterAttributes.put(name, value);
    }

    public void addDefaultSearchFilterAttribute(String name, String value) {
        defaultSearchFilterAttributes.put(name, value);
    }

    public void setDefaultSearchable(boolean defaultSearchable) {
        this.defaultSearchable = defaultSearchable;
    }

    public boolean isDefaultSearchable() {
        return defaultSearchable;
    }

    public void setDefaultSearchPriority(int defaultSearchPriority) {
        this.defaultSearchPriority = defaultSearchPriority;
    }

    public int getDefaultSearchPriority() {
        return defaultSearchPriority;
    }

    public Dictionary<String, String> getModuleOverrideFilterAttributes() {
        return moduleOverrideFilterAttributes;
    }

    public Dictionary<String, String> getDefaultSearchFilterAttributes() {
        return defaultSearchFilterAttributes;
    }

    public void addStaticPath(String staticPath, boolean i18n) {
        staticPaths.add(staticPath);
        if (i18n) {
            i18nPaths.add(staticPath);
        }
    }

    public List<String> getStaticPaths() {
        return staticPaths;
    }

    public boolean isI18NPath(String staticPath) {
        return i18nPaths.contains(staticPath);
    }

    @Override
    public String toString() {
        return "MODULE " + name;
    }

    public static ModuleDescriptor read(URL url, Log log) throws Exception {
        ModuleDescriptor moduleInfo;
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        DocumentBuilder builder = factory.newDocumentBuilder();
        InputStream in = url.openStream();
        Document document;
        try {
            document = builder.parse(url.openStream());
        } finally {
            in.close();
        }
        Element root = document.getDocumentElement();
        if (root.getLocalName().equals("module-descriptor")) {
            String nsuri = root.getNamespaceURI();
            if (nsuri == null) {
                log.warn("Module descriptor file '" + url.toString() + "' declares no namespace.");
            } else if (!nsuri.equals(NS_MODULE_DESCRIPTOR)) {
                log.warn("Module descriptor file '" + url.toString() + "' declares wrong namespace: " + nsuri);
            }
            Element nameElem = getSingleChildElement(root, "module-name", true);
            String name = nameElem.getTextContent().trim();
            if (name.equals(""))
                throw new Exception("Text content of element 'module-name' must not be empty!");
            moduleInfo = new ModuleDescriptor(url, name);
            Element resPathElem = getSingleChildElement(root, "resource-path", false);
            if (resPathElem != null) {
                String resPath = resPathElem.getTextContent().trim();
                if (resPath.length() > 0) {
                    if (!resPath.startsWith("/")) {
                        resPath = "/" + resPath;
                    }
                    if (resPath.endsWith("/")) {
                        resPath = resPath.substring(0, resPath.length() - 1);
                    }
                    moduleInfo.setResourcePath(resPath);
                }
            }
            Element editElem = getSingleChildElement(root, "content-editable", false);
            if (editElem != null) {
                boolean editable = Boolean.valueOf(editElem.getTextContent());
                moduleInfo.setContentEditable(editable);
            }
            Element searchElem = getSingleChildElement(root, "default-search", false);
            if (searchElem != null) {
                moduleInfo.setDefaultSearchable(true);
                String priority = searchElem.getAttribute("priority").trim();
                if (priority.length() > 0) {
                    moduleInfo.setDefaultSearchPriority(Integer.parseInt(priority));
                }
                List<Element> filterAttrElems = getChildElements(searchElem, "filter-attribute");
                for (Element filterAttrElem : filterAttrElems) {
                    String filterAttrName = filterAttrElem.getAttribute("name");
                    if (filterAttrName.equals(""))
                        throw new Exception("Element 'filter-attribute' requires 'name' attribute!");
                    String filterAttrValue = filterAttrElem.getAttribute("value");
                    if (filterAttrValue.equals(""))
                        throw new Exception("Element 'filter-attribute' requires 'value' attribute!");
                    moduleInfo.addDefaultSearchFilterAttribute(filterAttrName, filterAttrValue);
                }
            }
            Element overElem = getSingleChildElement(root, "override-modules", false);
            if (overElem != null) {
                List<Element> filterAttrElems = getChildElements(overElem, "filter-attribute");
                for (Element filterAttrElem : filterAttrElems) {
                    String filterAttrName = filterAttrElem.getAttribute("name");
                    if (filterAttrName.equals(""))
                        throw new Exception("Element 'filter-attribute' requires 'name' attribute!");
                    String filterAttrValue = filterAttrElem.getAttribute("value");
                    if (filterAttrValue.equals(""))
                        throw new Exception("Element 'filter-attribute' requires 'value' attribute!");
                    moduleInfo.addModuleOverrideFilterAttribute(filterAttrName, filterAttrValue);
                }
                List<Element> modElems = getChildElements(overElem, "module");
                for (Element modElem : modElems) {
                    String modName = modElem.getAttribute("name").trim();
                    if (modName.equals(""))
                        throw new Exception("Element 'module' requires 'name' attribute!");
                    List<Element> resElems = getChildElements(modElem, "resource");
                    for (Element resElem : resElems) {
                        String resPath = resElem.getAttribute("path").trim();
                        if (resPath.equals(""))
                            throw new Exception("Element 'resource' requires 'path' attribute!");
                        moduleInfo.addOverridedResource(modName, resPath);
                    }
                }
            }
            Element staticElem = getSingleChildElement(root, "static", false);
            if (staticElem != null) {
                List<Element> pathElems = getChildElements(staticElem, "path");
                for (Element pathElem : pathElems) {
                    String path = pathElem.getTextContent().trim();
                    if (!path.equals("")) {
                        if (!path.startsWith("/"))
                            path = "/" + path;
                        if (path.endsWith("/"))
                            path = path.substring(0, path.length() - 1);
                        if (path.equals("") || path.equals(moduleInfo.getResourcePath()))
                            path = "/";
                        else if (path.startsWith(moduleInfo.getResourcePath()))
                            path = path.substring(moduleInfo.getResourcePath().length());
                        boolean i18n = false;
                        String i18nAttr = pathElem.getAttribute("i18n").trim();
                        if (i18nAttr.length() > 0) {
                            i18n = Boolean.parseBoolean(i18nAttr);
                        }
                        moduleInfo.addStaticPath(path, i18n);
                    }
                }
            }
        } else
            throw new Exception("Illegal module descriptor");
        return moduleInfo;
    }

    private static Element getSingleChildElement(Element parent, String localName, boolean mandatory)
            throws Exception {
        Element elem = null;
        NodeList nodes = parent.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE && node.getLocalName().equals(localName)) {
                if (elem != null)
                    throw new Exception("Multiple '" + localName + "' child elements aren't allowed.");
                elem = (Element) node;
            }
        }
        if (mandatory && elem == null)
            throw new Exception("Missing '" + localName + "' child element.");
        return elem;
    }

    private static List<Element> getChildElements(Element parent, String localName) {
        List<Element> elems = new ArrayList<Element>();
        NodeList nodes = parent.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE && node.getLocalName().equals(localName)) {
                elems.add((Element) node);
            }
        }
        return elems;
    }

}