net.wastl.webmail.server.Storage.java Source code

Java tutorial

Introduction

Here is the source code for net.wastl.webmail.server.Storage.java

Source

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

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;

import javax.servlet.UnavailableException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Templates;

import net.wastl.webmail.config.ConfigScheme;
import net.wastl.webmail.exceptions.BinaryNotFoundException;
import net.wastl.webmail.exceptions.CreateUserDataException;
import net.wastl.webmail.exceptions.InvalidPasswordException;
import net.wastl.webmail.exceptions.UserDataException;
import net.wastl.webmail.exceptions.WebMailException;
import net.wastl.webmail.xml.XMLAdminModel;
import net.wastl.webmail.xml.XMLGenericModel;
import net.wastl.webmail.xml.XMLSystemData;
import net.wastl.webmail.xml.XMLUserData;
import net.wastl.webmail.xml.XMLUserModel;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.SAXException;

/**
 * This provides a generic interface for getting and setting stored
 * data in WebMail.
 *
 * @see net.wastl.webmail.storage.simple.SimpleStorage
 * @author Sebastian Schaffert
*/
public abstract class Storage {
    private static Log log = LogFactory.getLog(Storage.class);

    protected WebMailServer parent;

    protected ConfigScheme cs;

    protected XMLSystemData sysdata;

    protected XMLGenericModel generic_model;

    public Storage(WebMailServer parent) {
        this.parent = parent;
        cs = parent.getConfigScheme();
        cs.configRegisterYesNoKey("FOLDER TRY LOGIN PASSWORD",
                "Try to connect folders with the user's login password if authentication fails");
    }

    public void initConfigKeys() {
        // Initialize the configuration file with the default or set parameters
        // needed to complete the XML file
        for (String key : cs.getPossibleKeys()) {
            if (!sysdata.isConfigSet(key)) {
                // We must use the raw method so the input doesn't get filtered.
                sysdata.setConfig(key, (String) cs.getDefaultValue(key), false, false);
            }
        }
        saveXMLSysData();
    }

    /**
     * Fetch all keys of the current configuration.
     */
    public Set<String> getConfigKeys() {
        return cs.getPossibleKeys();
    }

    /**
     * Fetch the configuration associated with the specified key.
     * @param key Identifier for the configuration
     */
    public String getConfig(String key) {
        return sysdata.getConfig(key);
    }

    /**
     * Set a configuration "key" to the specified value.
     * @param key Identifier for the configuration
     * @param value value to set
      */
    public void setConfig(String key, String value) throws IllegalArgumentException {
        /**
         * Maybe here is a bug.
         *
         * Consider that if administrator happens to delete the value of certain
         * key, that is, the key is an empty tag.
         * FileStorage.java:272 call ConfigScheme.configRegister???Key() to set
         * value first, which becomes a default value, then call this function.
         * However, ConfigStore.getConfig() returns default value
         * if the key is an empty tag in configuration file that getConfigRaw()
         * returns null/empty value. That means the value passing in here is always
         * equals to the value returned by ConfigStore.getConfig().
         *
         * The simplest way to enforce saving config data is to comment out the
         * if statement. However, this may be a performance issue, so I don't
         * modify the code.
         */
        if (!value.equals(getConfig(key))) {
            log.debug("Storage API: Setting configuration for '" + key + "' to '" + value + "'.");
            sysdata.setConfig(key, value);
            saveXMLSysData();
        }
    }

    /**
     * Get the String for key and the specified locale.
     * @param key Identifier for the String
     * @param locale locale of the String to fetch
     */
    public abstract String getStringResource(String key, Locale locale);

    /**
      * Get a xsl stylesheet for the specified locale and theme.
      * @param key Identifier for the String
      * @param locale locale of the String to fetch
      * @param theme theme where to look for the file
      */
    public abstract Templates getStylesheet(String name, Locale locale, String theme) throws WebMailException;

    /**
      * Get a binary file (most likely an image) for the specified locale and theme.
      * @param key Identifier for the String
      * @param locale locale of the String to fetch
      * @param theme theme where to look for the file
      */
    public abstract byte[] getBinaryFile(String name, Locale locale, String theme) throws BinaryNotFoundException;

    /**
     * Calculate the document base path for a given locale and theme
     */
    public String getBasePath(Locale locale, String theme) {
        String language_path = (parent.getProperty("webmail.template.path") + System.getProperty("file.separator")
                + locale.getLanguage());
        File f = new File(language_path);
        if (!f.exists()) {
            language_path = (parent.getProperty("webmail.template.path") + System.getProperty("file.separator")
                    + parent.getDefaultLocale().getLanguage());
            f = new File(language_path);
            if (!f.exists()) {
                log.error("Storage::getBasePath: Default Language templates not found \n(tried path: "
                        + language_path + ")");
            }
        }
        String theme_path = language_path + System.getProperty("file.separator") + theme;
        f = new File(theme_path);
        if (!f.exists()) {
            if (parent.getProperty("webmail.default.theme") != null) {
                theme_path = language_path + System.getProperty("file.separator")
                        + parent.getProperty("webmail.default.theme");
            } else {
                theme_path = language_path + System.getProperty("file.separator") + "bibop";
            }
            f = new File(theme_path);
            if (!f.exists()) {
                log.error(
                        "Storage::getBasePath: Theme could not be found; probably a problem with your\n installation. Please check the lib/templates/bibop directory and the \nwebmail.default.theme property");
            }
        }
        String basepath = theme_path + System.getProperty("file.separator");
        return basepath;
    }

    public XMLSystemData getSystemData() {
        return sysdata;
    }

    public XMLUserModel createXMLUserModel(XMLUserData data) throws WebMailException {
        try {
            return new XMLUserModel(parent, sysdata.getSysData(), data.getUserData());
        } catch (ParserConfigurationException pce) {
            throw new WebMailException("Creating the generic XML model failed. Reason: " + pce.getMessage());
        } catch (SAXException saxe) {
            throw new WebMailException("SAXException thrown. Reason: " + saxe.getMessage());
        } catch (IOException ioe) {
            throw new WebMailException("IOException thrown. Reason: " + ioe.getMessage());
        }
    }

    /**
     * Return a XML model that contains state and system information for administrator use
     */
    public XMLAdminModel createXMLAdminModel() throws WebMailException {
        try {
            XMLAdminModel model = new XMLAdminModel(parent, sysdata.getSysData());
            model.init();
            model.update();
            return model;
        } catch (ParserConfigurationException pce) {
            throw new WebMailException("Creating the generic XML model failed. Reason: " + pce.getMessage());
        } catch (SAXException saxe) {
            throw new WebMailException("Creating the generic XML model failed. Reason: " + saxe.getMessage());
        } catch (IOException ioe) {
            throw new WebMailException("Creating the generic XML model failed. Reason: " + ioe.getMessage());
        }
    }

    /**
     * Return a generic XML model that only contains some state and system information.
     * This cannot be changed by a single session.
     */
    public XMLGenericModel createXMLGenericModel() throws WebMailException {
        try {
            XMLGenericModel model = new XMLGenericModel(parent, sysdata.getSysData());
            model.init();
            model.update();
            return model;
        } catch (ParserConfigurationException pce) {
            throw new WebMailException("Creating the generic XML model failed. Reason: " + pce.getMessage());
        } catch (SAXException saxe) {
            throw new WebMailException("SAXException thrown. Reason: " + saxe.getMessage());
        } catch (IOException ioe) {
            throw new WebMailException("IOException thrown. Reason: " + ioe.getMessage());
        }
    }

    /**
     * Return userlist for a given domain.
     */
    public abstract Enumeration getUsers(String domain);

    /**
     * @deprecated Use getUsers(String domain) instead
     */
    @Deprecated
    public Enumeration getUsers() {
        final Enumeration domains = getVirtualDomains();
        return new Enumeration() {
            Enumeration enumVar = null;

            public boolean hasMoreElements() {
                return (domains.hasMoreElements() || (enumVar != null && enumVar.hasMoreElements()));
            }

            public Object nextElement() {
                if (enumVar == null || !enumVar.hasMoreElements()) {
                    if (domains.hasMoreElements()) {
                        enumVar = getUsers((String) domains.nextElement());
                    } else {
                        return null;
                    }
                }
                return enumVar.nextElement();
            }
        };
    }

    /**
     * Get the userdata for the specified user.
     * @param user Name of the user
     * @param domain Virtual Domain name of the user
     * @param passwd Password that the user provided
     * XXX should passwd be a parameter?
     */
    public XMLUserData getUserData(String user, String domain, String passwd)
            throws UserDataException, InvalidPasswordException {
        return getUserData(user, domain, passwd, false);
    }

    /**
     * get the userdata for the specified user.
     * Should do some sort of authentication if authentication is set. See
     * Authenticator class for example.
     * no requirement to implement it.
     */
    public abstract XMLUserData getUserData(String user, String domain, String password, boolean authenticate)
            throws UserDataException, InvalidPasswordException;

    /**
     * Create a userdata for the specified user
     */
    public abstract XMLUserData createUserData(String user, String domain, String password)
            throws CreateUserDataException;

    /**
     * Save the userdata for the given user.
     * @param user Username of this user
     * @param domain Domain of this user
     */
    public abstract void saveUserData(String user, String domain);

    /**
     * Set the userdata for the specified user.
     * @param user Name of the user
     * @param userdata Data to store
     * @deprecated use saveUserData instead.
     */
    @Deprecated
    public void setUserData(String user, UserData userdata) {
        // Call saveUserData, do nothing with "userdata"
        StringTokenizer tok = new StringTokenizer(user, "@");
        String login = tok.nextToken();
        String domain = "nodomain";
        if (tok.hasMoreTokens()) {
            domain = tok.nextToken();
        }
        saveUserData(login, domain);
    }

    /**
     * Delete a WebMail user
     * @param user Name of the user to delete
     * @param domain Domain of that user
     */
    public abstract void deleteUserData(String user, String domain);

    /**
     * Delete a WebMail user
     * @param user Name of the user to delete
     * @deprecated use deleteUserData(String user, String domain) instead.
     */
    @Deprecated
    public void deleteUserData(String user) {
        StringTokenizer tok = new StringTokenizer(user, "@");
        String login = tok.nextToken();
        String domain = "nodomain";
        if (tok.hasMoreTokens()) {
            domain = tok.nextToken();
        }
        deleteUserData(user, domain);
    }

    /**
     * Get virtuals
     */
    public boolean getVirtuals() {
        return sysdata.getVirtuals();
    }

    public void setVirtuals(boolean state) {
        sysdata.setVirtuals(state);
        saveXMLSysData();
    }

    /**
     * Set/add a WebMail virtual domain
     */
    public void setVirtualDomain(String name, WebMailVirtualDomain v) {
        sysdata.setVirtualDomain(name, v);
        saveXMLSysData();
    }

    /**
     * Get a WebMail virtual domain
     */
    public WebMailVirtualDomain getVirtualDomain(String name) {
        return sysdata.getVirtualDomain(name);
    }

    public WebMailVirtualDomain createVirtualDomain(String name) throws Exception {
        sysdata.createVirtualDomain(name);
        return sysdata.getVirtualDomain(name);
    }

    /**
     * Delete a WebMail virtual domain
     */
    public void deleteVirtualDomain(String name) {
        sysdata.deleteVirtualDomain(name);
    }

    /**
     * Return a list of virtual domains
     */
    public Enumeration getVirtualDomains() {
        return sysdata.getVirtualDomains();
    }

    /**
     * Return this Storage's Authenticator.
     * This is necessary for changing passwords or re-checking authentication.
     */
    public abstract Authenticator getAuthenticator();

    public abstract void shutdown();

    public void save() {
        saveXMLSysData();
    }

    protected abstract void loadXMLSysData() throws UnavailableException;

    protected abstract void saveXMLSysData();

    public String getMimeType(String name) {
        String content_type;
        if (name != null && (name.toLowerCase().endsWith("jpg") || name.toLowerCase().endsWith("jpeg"))) {
            content_type = "IMAGE/JPEG";
        } else if (name != null && name.toLowerCase().endsWith("gif")) {
            content_type = "IMAGE/GIF";
        } else if (name != null && name.toLowerCase().endsWith("png")) {
            content_type = "IMAGE/PNG";
        } else if (name != null && name.toLowerCase().endsWith("txt")) {
            content_type = "TEXT/PLAIN";
        } else if (name != null && (name.toLowerCase().endsWith("htm") || name.toLowerCase().endsWith("html"))) {
            content_type = "TEXT/HTML";
        } else {
            content_type = "APPLICATION/OCTET-STREAM";
        }
        return content_type;
    }
}