net.wastl.webmail.xml.XMLSystemData.java Source code

Java tutorial

Introduction

Here is the source code for net.wastl.webmail.xml.XMLSystemData.java

Source

/*
 * @(#)$Id: XMLSystemData.java 116 2008-10-30 06:12:51Z unsaved $
 *
 * Copyright 2008 by the JWebMail Development Team and Sebastian Schaffert.
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.wastl.webmail.xml;

import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;

import net.wastl.webmail.config.ChoiceConfigParameter;
import net.wastl.webmail.config.ConfigParameter;
import net.wastl.webmail.config.ConfigScheme;
import net.wastl.webmail.config.ConfigStore;
import net.wastl.webmail.server.WebMailVirtualDomain;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * This class represents methods for accessing WebMail's system configuration in a
 * XML tree.
 *
 * @author Sebastian Schaffert
 */
public class XMLSystemData extends ConfigStore {
    private static Log log = LogFactory.getLog(ConfigStore.class);

    protected Document root;

    protected Element sysdata;

    /* Save the time when this document has been loaded. Might be used to reload
       a document with a higher modification time
    */
    protected long loadtime;

    public XMLSystemData(Document d, ConfigScheme cs) {
        super(cs);
        root = d;
        sysdata = root.getDocumentElement();
        if (sysdata == null) {
            sysdata = root.createElement("SYSDATA");
            root.appendChild(sysdata);
        }
        loadtime = System.currentTimeMillis();
    }

    public long getLoadTime() {
        return loadtime;
    }

    public void setLoadTime(long time) {
        loadtime = time;
    }

    public Document getRoot() {
        return root;
    }

    public Element getSysData() {
        return sysdata;
    }

    public DocumentFragment getDocumentFragment() {
        DocumentFragment df = root.createDocumentFragment();
        df.appendChild(sysdata);
        return df;
    }

    protected String getConfigRaw(String key) {
        NodeList nl = sysdata.getElementsByTagName("KEY");
        for (int i = 0; i < nl.getLength(); i++) {
            Element e = (Element) nl.item(i);
            if (XMLCommon.getElementTextValue(e).equals(key)) {
                Element p = (Element) e.getParentNode();
                NodeList valuel = p.getElementsByTagName("VALUE");
                if (valuel.getLength() >= 0) {
                    return XMLCommon.getElementTextValue((Element) valuel.item(0));
                }
            }
        }
        return null;
    }

    public void setConfigRaw(String groupname, String key, String value, String type) {
        String curval = getConfigRaw(key);
        if (curval == null || !curval.equals(value)) {
            log.debug("XMLSystemData: " + groupname + "/" + key + " = " + value);
            /* Find all GROUP elements */
            NodeList groupl = sysdata.getElementsByTagName("GROUP");
            int i = 0;
            for (i = 0; i < groupl.getLength(); i++) {
                Element group = (Element) groupl.item(i);
                if (group.getAttribute("name").equals(groupname)) {
                    /* If the group name matches, find all keys */
                    NodeList keyl = group.getElementsByTagName("KEY");
                    int j = 0;
                    for (j = 0; j < keyl.getLength(); j++) {
                        Element keyelem = (Element) keyl.item(j);
                        if (key.equals(XMLCommon.getElementTextValue(keyelem))) {
                            /* If the key already exists, replace it */
                            Element conf = (Element) keyelem.getParentNode();
                            group.replaceChild(createConfigElement(key, value, type), conf);
                            return;
                        }
                    }
                    /* If the key was not found, append it */
                    if (j >= keyl.getLength()) {
                        group.appendChild(createConfigElement(key, value, type));
                        return;
                    }
                }
            }
            if (i >= groupl.getLength()) {
                Element group = createConfigGroup(groupname);
                group.appendChild(createConfigElement(key, value, type));
            }
        }
    }

    protected Element createConfigGroup(String groupname) {
        Element group = root.createElement("GROUP");
        group.setAttribute("name", groupname);
        sysdata.appendChild(group);
        return group;
    }

    protected void deleteConfigGroup(String groupname) {
        NodeList nl = sysdata.getElementsByTagName("GROUP");
        for (int i = 0; i < nl.getLength(); i++) {
            if (((Element) nl.item(i)).getAttribute("name").equals(groupname)) {
                sysdata.removeChild(nl.item(i));
            }
        }
    }

    protected Element getConfigElementByKey(String key) {
        NodeList nl = sysdata.getElementsByTagName("KEY");

        Element config = null;
        for (int i = 0; i < nl.getLength(); i++) {
            Element keyelem = (Element) nl.item(i);
            Element parent = (Element) keyelem.getParentNode();
            if (XMLCommon.getElementTextValue(keyelem).equals(key) && parent.getTagName().equals("CONFIG")) {
                config = parent;
                break;
            }
        }
        return config;
    }

    public void initChoices() {
        for (String configKey : getConfigKeys())
            initChoices(configKey);
    }

    public void initChoices(String key) {
        Element config = getConfigElementByKey(key);

        XMLCommon.genericRemoveAll(config, "CHOICE");

        ConfigParameter param = scheme.getConfigParameter(key);
        if (param instanceof ChoiceConfigParameter) {
            Enumeration enumVar = ((ChoiceConfigParameter) param).choices();
            while (enumVar.hasMoreElements()) {
                Element choice = root.createElement("CHOICE");
                choice.appendChild(root.createTextNode((String) enumVar.nextElement()));
                config.appendChild(choice);
            }
        }
    }

    protected Element createConfigElement(String key, String value, String type) {
        Element config = root.createElement("CONFIG");
        Element keyelem = root.createElement("KEY");
        Element desc = root.createElement("DESCRIPTION");
        Element valueelem = root.createElement("VALUE");
        keyelem.appendChild(root.createTextNode(key));
        desc.appendChild(root.createTextNode(scheme.getDescription(key)));
        valueelem.appendChild(root.createTextNode(value));
        config.appendChild(keyelem);
        config.appendChild(desc);
        config.appendChild(valueelem);
        config.setAttribute("type", type);
        ConfigParameter param = scheme.getConfigParameter(key);
        if (param instanceof ChoiceConfigParameter) {
            Enumeration enumVar = ((ChoiceConfigParameter) param).choices();
            while (enumVar.hasMoreElements()) {
                Element choice = root.createElement("CHOICE");
                choice.appendChild(root.createTextNode((String) enumVar.nextElement()));
                config.appendChild(choice);
            }
        }
        return config;
    }

    public boolean getVirtuals() {
        final NodeList nl = sysdata.getElementsByTagName("VIRTUALS");
        Element virtuals = (Element) nl.item(0);
        if (virtuals != null && virtuals.getAttribute("enabled") != null
                && virtuals.getAttribute("enabled").equals("true")) {
            return true;
        } else {
            return false;
        }
    }

    public void setVirtuals(boolean state) {
        NodeList nl = sysdata.getElementsByTagName("VIRTUALS");
        Element virtuals = (Element) nl.item(0);
        if (state == false) {
            virtuals.setAttribute("enabled", "false");
        } else {
            virtuals.setAttribute("enabled", "true");
        }
    }

    public Enumeration getVirtualDomains() {
        final NodeList nl = sysdata.getElementsByTagName("DOMAIN");
        return new Enumeration() {
            int i = 0;

            public boolean hasMoreElements() {
                return i < nl.getLength();
            }

            public Object nextElement() {
                Element elem = (Element) nl.item(i++);
                String value = XMLCommon.getTagValue(elem, "NAME");
                return value == null ? "unknown" + (i - 1) : value;
            }
        };
    }

    public WebMailVirtualDomain getVirtualDomain(String domname) {
        // Check if virtual domains are disabled
        if (getVirtuals() == false) {
            // No, default to localhost
            return new WebMailVirtualDomain() {
                public String getDomainName() {
                    return "localhost";
                }

                public void setDomainName(String name) throws Exception {
                    log.error("Ignoring DefaultDomain.setDomainName().  " + "Should not call this method.");
                }

                public String getDefaultServer() {
                    return "localhost";
                }

                public void setDefaultServer(String name) {
                    log.error("Ignoring DefaultDomain.setDomainServer().  " + "Should not call this method.");
                }

                public String getAuthenticationHost() {
                    return "localhost";
                }

                public void setAuthenticationHost(String name) {
                    log.error("Ignoring DefaultDomain.setAuthenticationHost().  " + "Should not call this method.");
                }

                public boolean isAllowedHost(String host) {
                    return true;
                }

                public void setAllowedHosts(String hosts) {
                    log.error("Ignoring DefaultDomain.setAllowedHosts().  " + "Should not call this method.");
                }

                public Enumeration<String> getAllowedHosts() {
                    return new Enumeration<String>() {
                        int i = 0;

                        public boolean hasMoreElements() {
                            return i < 1;
                        }

                        public String nextElement() {
                            i++;
                            return "localhost";
                        }
                    };
                }

                public void setHostsRestricted(boolean b) {
                    log.error("Ignoring DefaultDomain.setHostsRestricted().  " + "Should not call this method.");
                }

                public boolean getHostsRestricted() {
                    return false;
                }

                public String getImapBasedir() {
                    return null;
                }
            };
        }
        // Virtual domains are allowed, get that wanted one
        NodeList nodel = sysdata.getElementsByTagName("DOMAIN");
        Element elem = null;
        int j;
        for (j = 0; j < nodel.getLength(); j++) {
            elem = (Element) nodel.item(j);
            elem.normalize();
            NodeList namel = elem.getElementsByTagName("NAME");
            if (namel.getLength() > 0) {
                if (XMLCommon.getElementTextValue((Element) namel.item(0)).equals(domname)) {
                    break;
                }
            }
        }
        if (j < nodel.getLength() && elem != null) {
            final Element domain = elem;
            return new WebMailVirtualDomain() {
                public String getDomainName() {
                    String value = XMLCommon.getTagValue(domain, "NAME");
                    return value == null ? "unknown" : value;
                }

                public void setDomainName(String name) throws Exception {
                    XMLCommon.setTagValue(domain, "NAME", name, true, "Virtual Domain names must be unique!");
                }

                public String getDefaultServer() {
                    String value = XMLCommon.getTagValue(domain, "DEFAULT_HOST");
                    return value == null ? "unknown" : value;
                }

                /* Override the IMAP base directory for this domain,
                 * for imap and imaps protocols */
                public String getImapBaseDir() {
                    String value = XMLCommon.getTagValue(domain, "IMAP_BASEDIR");
                    return value == null ? "unknown" : value;
                }

                public void setDefaultServer(String name) {
                    XMLCommon.setTagValue(domain, "DEFAULT_HOST", name);
                }

                public String getAuthenticationHost() {
                    String value = XMLCommon.getTagValue(domain, "AUTHENTICATION_HOST");
                    return value == null ? "unknown" : value;
                }

                public void setAuthenticationHost(String name) {
                    XMLCommon.setTagValue(domain, "AUTHENTICATION_HOST", name);
                }

                public boolean isAllowedHost(String host) {
                    if (getHostsRestricted()) {
                        Vector<String> v = new Vector<String>();
                        v.addElement(getDefaultServer());
                        Enumeration<String> e = getAllowedHosts();
                        while (e.hasMoreElements()) {
                            v.addElement(e.nextElement());
                        }
                        Enumeration<String> enumVar = v.elements();
                        while (enumVar.hasMoreElements()) {
                            String next = enumVar.nextElement();
                            if (host.toUpperCase().endsWith(next.toUpperCase())) {
                                return true;
                            }
                        }
                        return false;
                    } else {
                        return true;
                    }
                }

                public void setAllowedHosts(String hosts) {
                    NodeList nl = domain.getElementsByTagName("ALLOWED_HOST");
                    for (int i = 0; i < nl.getLength(); i++) {
                        domain.removeChild(nl.item(i));
                    }
                    StringTokenizer tok = new StringTokenizer(hosts, ", ");
                    while (tok.hasMoreElements()) {
                        Element ahost = root.createElement("ALLOWED_HOST");
                        XMLCommon.setElementTextValue(ahost, tok.nextToken());
                        domain.appendChild(ahost);
                    }
                }

                public Enumeration<String> getAllowedHosts() {
                    final NodeList nl = domain.getElementsByTagName("ALLOWED_HOST");
                    return new Enumeration<String>() {
                        int i = 0;

                        public boolean hasMoreElements() {
                            return i < nl.getLength();
                        }

                        public String nextElement() {
                            String value = XMLCommon.getElementTextValue((Element) nl.item(i++));
                            return value == null ? "error" : value;
                        }
                    };
                }

                public void setHostsRestricted(boolean b) {
                    NodeList nl = domain.getElementsByTagName("RESTRICTED");
                    for (int i = 0; i < nl.getLength(); i++) {
                        domain.removeChild(nl.item(i));
                    }
                    if (b) {
                        domain.appendChild(root.createElement("RESTRICTED"));
                    }
                }

                public boolean getHostsRestricted() {
                    NodeList nl = domain.getElementsByTagName("RESTRICTED");
                    return nl.getLength() > 0;
                }

                public String getImapBasedir() {
                    NodeList nl = domain.getElementsByTagName("IMAP_BASEDIR");
                    return ((nl.getLength() > 0) ? XMLCommon.getElementTextValue((Element) nl.item(0)) : null);
                }
            };
        } else {
            return null;
        }
    }

    /**
     * This is just completely useless, since you can change virtual domains directly.
     * It should be removed ASAP
     */
    public void setVirtualDomain(String name, WebMailVirtualDomain domain) {
        log.fatal("Called useless net.wastl.webmail.xml.XMLSystemData::setVirtualDomain/2");
        // TODO: Throw here, so we will be confident this is not used
    }

    public void deleteVirtualDomain(String name) {
        NodeList nl = sysdata.getElementsByTagName("NAME");
        for (int i = 0; i < nl.getLength(); i++) {
            if (nl.item(i).getParentNode().getNodeName().equals("DOMAIN")
                    && XMLCommon.getElementTextValue((Element) nl.item(i)).equals(name)) {
                sysdata.removeChild(nl.item(i).getParentNode());
            }
        }
        log.info("XMLSystemData: Deleted WebMail virtual domain " + name);
    }

    public void createVirtualDomain(String name) throws Exception {
        WebMailVirtualDomain dom = getVirtualDomain(name);
        if (dom != null) {
            throw new Exception("Domain names must be unique!");
        }
        Element domain = root.createElement("DOMAIN");
        sysdata.appendChild(domain);
        domain.appendChild(root.createElement("NAME"));
        domain.appendChild(root.createElement("DEFAULT_HOST"));
        domain.appendChild(root.createElement("AUTHENTICATION_HOST"));
        domain.appendChild(root.createElement("ALLOWED_HOST"));
        XMLCommon.setTagValue(domain, "NAME", name);
        XMLCommon.setTagValue(domain, "DEFAULT_HOST", "localhost");
        XMLCommon.setTagValue(domain, "AUTHENTICATION_HOST", "localhost");
        XMLCommon.setTagValue(domain, "ALLOWED_HOST", "localhost");
        log.info("XMLSystemData: Created WebMail virtual domain " + name);
    }
}