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

Java tutorial

Introduction

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

Source

/*
 * @(#)$Id: XMLUserModel.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.Vector;

import javax.xml.parsers.ParserConfigurationException;

import net.wastl.webmail.server.WebMailServer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Mainly consists of a DOM that represents all of the data in the user's session.
 * On subtrees, there are the SYSDATA and the USERDATA DOM trees (among other stuff like folder list,
 * message list, etc)
 *
 * Many methods here are synchronized but that shouldn't hurt performance too much since the cases where several
 * Threads access the model are rare anyway
 *
 * @author Sebastian Schaffert
 */
public class XMLUserModel extends XMLGenericModel {
    private static Log log = LogFactory.getLog(XMLUserModel.class);
    protected Element usermodel;

    protected Element userdata;

    public XMLUserModel(WebMailServer parent, Element rsysdata, Element ruserdata)
            throws ParserConfigurationException, org.xml.sax.SAXException, java.io.IOException {
        super(parent, rsysdata);

        usermodel = root.getDocumentElement();
        this.data = usermodel;

        this.userdata = ruserdata;

        update();
    }

    protected void initRoot() {
        // Create a new usermodel from the template file
        try {
            root = parser.parse("file://" + parent.getProperty("webmail.xml.path")
                    + System.getProperty("file.separator") + "usermodel_template.xml");
        } catch (Exception ex) {
            log.error("Error parsing WebMail UserModel template" + ex.getMessage(), ex);
            // Should this not throw?
        }
    }

    public synchronized void update() {
        // Insert the sysdata and userdata objects into the usermodel tree
        super.update();
        try {
            NodeList nl = root.getElementsByTagName("USERDATA");
            usermodel.replaceChild(root.importNode(userdata, true), nl.item(0));
            invalidateCache();
        } catch (ArrayIndexOutOfBoundsException ex) {
            log.error("The WebMail UserModel template file didn't contain a USERDATA tag.");
        } catch (DOMException ex) {
            log.error("Something went wrong with the XML user model", ex);
        }
    }

    public synchronized Element createFolder(String id, String name, boolean holds_folders,
            boolean holds_messages) {
        Element folder = root.createElement("FOLDER");
        folder.setAttribute("id", id);
        folder.setAttribute("name", name);
        folder.setAttribute("holds_folders", holds_folders + "");
        folder.setAttribute("holds_messages", holds_messages + "");
        return folder;
    }

    public synchronized Element getFolder(String id) {
        return XMLCommon.getElementByAttribute(usermodel, "FOLDER", "id", id);
    }

    public synchronized Element createMessageList() {
        Element messagelist = root.createElement("MESSAGELIST");
        return messagelist;
    }

    /**
     * Get messagelist for folder. Create if necessary.
     */
    public synchronized Element getMessageList(Element folder) {
        NodeList nl = folder.getChildNodes();
        Element messagelist = null;
        for (int i = 0; i < nl.getLength(); i++) {
            Element tmp = (Element) nl.item(i);
            if (tmp.getTagName().equals("MESSAGELIST")) {
                messagelist = tmp;
                break;
            }
        }
        if (messagelist == null) {
            messagelist = createMessageList();
            folder.appendChild(messagelist);
        }
        return messagelist;
    }

    public synchronized void removeMessageList(Element folder) {
        XMLCommon.genericRemoveAll(folder, "MESSAGELIST");
        invalidateCache();
    }

    /**
     * Check whether we already fetched this message. This can save a lot of time and CPU.
     */
    public synchronized boolean messageCached(Element folder, String msgid) {
        NodeList nl = folder.getElementsByTagName("MESSAGE");
        Element message = null;
        for (int i = 0; i < nl.getLength(); i++) {
            Element test = (Element) nl.item(i);
            if (test.getAttribute("msgid").equals(msgid)) {
                message = test;
                break;
            }
        }
        return message != null;
    }

    public synchronized XMLMessage getMessage(Element folder, String msgnr, String msgid) {
        NodeList nl = folder.getElementsByTagName("MESSAGE");
        Element message = null;
        for (int i = 0; i < nl.getLength(); i++) {
            Element test = (Element) nl.item(i);
            if (test.getAttribute("msgid").equals(msgid)) {
                message = test;
                break;
            }
        }
        if (message == null) {
            message = root.createElement("MESSAGE");
            message.setAttribute("msgid", msgid);
            Element msglist = getMessageList(folder);
            msglist.appendChild(message);
        }
        message.setAttribute("msgnr", msgnr);
        invalidateCache();
        return new XMLMessage(message);
    }

    /**
     * Return the WORK element that stores messages that are currently edited.
     */
    public synchronized XMLMessage getWorkMessage() {
        NodeList nl = usermodel.getElementsByTagName("WORK");
        Element work;
        if (nl.getLength() > 0) {
            work = (Element) nl.item(0);
        } else {
            work = root.createElement("WORK");
            usermodel.appendChild(work);
            invalidateCache();
        }
        nl = work.getElementsByTagName("MESSAGE");

        XMLMessage message;
        if (nl.getLength() > 0) {
            message = new XMLMessage((Element) nl.item(0));
        } else {
            message = new XMLMessage(root.createElement("MESSAGE"));
            work.appendChild(message.getMessageElement());
            message.setAttribute("msgnr", "0");
            message.setAttribute("msgid", WebMailServer.generateMessageID("webmailuser"));
            XMLMessagePart multipart = message.createPart("multi");
            multipart.createPart("text");
            invalidateCache();
        }
        return message;
    }

    public synchronized void clearWork() {
        NodeList nl = usermodel.getElementsByTagName("WORK");
        if (nl.getLength() > 0) {
            Element work = (Element) nl.item(0);
            NodeList nl2 = work.getChildNodes();
            Vector<Node> v = new Vector<Node>();
            for (int i = 0; i < nl2.getLength(); i++) {
                v.addElement(nl2.item(i));
            }
            Enumeration<Node> enumVar = v.elements();
            while (enumVar.hasMoreElements()) {
                work.removeChild(enumVar.nextElement());
            }
            invalidateCache();
        }
    }

    /**
     * Set the current work message (for forwarding and replying).
     * Note that this method uses importNode, therefore the newly
     * cloned message element is returned by this method.
     */
    public synchronized XMLMessage setWorkMessage(XMLMessage message) {
        clearWork();
        NodeList nl = usermodel.getElementsByTagName("WORK");
        Element work;
        if (nl.getLength() > 0) {
            work = (Element) nl.item(0);
        } else {
            work = root.createElement("WORK");
            usermodel.appendChild(work);
        }

        Element newmessage = (Element) root.importNode(message.getMessageElement(), true);
        work.appendChild(newmessage);
        invalidateCache();
        return new XMLMessage(newmessage);
    }

    public synchronized Element createMailhost(String name, String id, String url) {
        Element mh = root.createElement("MAILHOST_MODEL");
        mh.setAttribute("name", name);
        mh.setAttribute("id", id);
        if (url != null) {
            mh.setAttribute("url", url);
        }
        return mh;
    }

    /**
     * Add a previously created Mailhost to the DOM.
     * The Mailhost should already contain all the subfolders.:-)
     */
    public synchronized void addMailhost(Element mh) {
        String name = mh.getAttribute("name");
        Element elem = XMLCommon.getElementByAttribute(usermodel, "MAILHOST_MODEL", "name", name);
        if (elem == null) {
            usermodel.appendChild(mh);
        } else {
            usermodel.replaceChild(mh, elem);
        }
        invalidateCache();
    }

    protected synchronized Element setCurrent(String type, String id) {
        NodeList nl = usermodel.getElementsByTagName("CURRENT");
        Element current = null;
        for (int i = 0; i < nl.getLength(); i++) {
            if (((Element) nl.item(i)).getAttribute("type").equals(type)) {
                current = (Element) nl.item(i);
                break;
            }
        }
        if (current == null) {
            current = root.createElement("CURRENT");
            current.setAttribute("type", type);
            usermodel.appendChild(current);
        }
        current.setAttribute("id", id);
        invalidateCache();
        return current;
    }

    protected synchronized Element getCurrent(String type, String id) {
        NodeList nl = usermodel.getElementsByTagName("CURRENT");
        Element current = null;
        for (int i = 0; i < nl.getLength(); i++) {
            if (((Element) nl.item(i)).getAttribute("type").equals(type)) {
                current = (Element) nl.item(i);
                break;
            }
        }
        return current;
    }

    public Element setCurrentMessage(String id) {
        return setCurrent("message", id);
    }

    public Element setCurrentFolder(String id) {
        return setCurrent("folder", id);
    }

    public Element getCurrentMessage(String id) {
        return getCurrent("message", id);
    }

    public Element getCurrentFolder(String id) {
        return getCurrent("folder", id);
    }
}