Java tutorial
/* * @(#)$Id: SimpleStorage.java 111 2008-10-29 23:09:35Z 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.storage.simple; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.Enumeration; import java.util.Hashtable; import javax.servlet.UnavailableException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import net.wastl.webmail.exceptions.CreateUserDataException; import net.wastl.webmail.exceptions.InvalidPasswordException; import net.wastl.webmail.exceptions.UserDataException; import net.wastl.webmail.misc.ExpireableCache; import net.wastl.webmail.server.WebMailServer; import net.wastl.webmail.server.WebMailVirtualDomain; import net.wastl.webmail.storage.FileStorage; import net.wastl.webmail.xml.XMLCommon; import net.wastl.webmail.xml.XMLSystemData; import net.wastl.webmail.xml.XMLUserData; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; import org.xml.sax.InputSource; /** * This is the SimpleStorage class for the non-enterprise edition of WebMail. * It provides means of getting and storing data in ZIPFiles and * ResourceBundles. * * @see net.wastl.webmail.server.Storage * @author Sebastian Schaffert * @versin $Revision: 111 $ */ public class SimpleStorage extends FileStorage { private static Log log = LogFactory.getLog(FileStorage.class); public static final String user_domain_separator = "|"; protected Hashtable resources; protected Hashtable vdoms; protected ExpireableCache user_cache; protected int user_cache_size = 100; /** * Initialize SimpleStorage. * Fetch Configuration Information etc. */ public SimpleStorage(WebMailServer parent) throws UnavailableException { super(parent); saveXMLSysData(); } protected void initConfig() throws UnavailableException { log.info("Configuration ... "); loadXMLSysData(); log.info("successfully parsed XML configuration file."); } protected void loadXMLSysData() throws UnavailableException { String datapath = parent.getProperty("webmail.data.path"); String file = "file://" + datapath + System.getProperty("file.separator") + "webmail.xml"; // String file=datapath+System.getProperty("file.separator")+"webmail.xml"; // bug fixed by Christian Senet Document root; try { DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); root = parser.parse(file); log.debug("Configuration file parsed, document: " + root); sysdata = new XMLSystemData(root, cs); log.debug("SimpleStorage: WebMail configuration loaded."); } catch (Exception ex) { log.error("SimpleStorage: Failed to load WebMail configuration file", ex); throw new UnavailableException(ex.getMessage()); } } protected void saveXMLSysData() { try { Document d = sysdata.getRoot(); OutputStream cfg_out = new FileOutputStream( parent.getProperty("webmail.data.path") + System.getProperty("file.separator") + "webmail.xml"); XMLCommon.writeXML(d, cfg_out, "file://" + parent.getProperty("webmail.xml.path") + System.getProperty("file.separator") + "sysdata.dtd"); // XMLCommon.writeXML(d,cfg_out,parent.getProperty("webmail.xml.path")+ // System.getProperty("file.separator")+"sysdata.dtd"); cfg_out.flush(); cfg_out.close(); sysdata.setLoadTime(System.currentTimeMillis()); log.debug("SimpleStorage: WebMail configuration saved."); } catch (Exception ex) { log.error("SimpleStorage: Error while trying to save WebMail configuration", ex); } } protected void initCache() { // Initialize the file cache from FileStorage super.initCache(); // Now initialize the user cache cs.configRegisterIntegerKey(this, "CACHE SIZE USER", "100", "Size of the user cache"); try { // Default value 100, if parsing fails. user_cache_size = 100; user_cache_size = Integer.parseInt(getConfig("CACHE SIZE USER")); } catch (NumberFormatException e) { } if (user_cache == null) { user_cache = new ExpireableCache(user_cache_size); } else { user_cache.setCapacity(user_cache_size); } } public Enumeration getUsers(String domain) { String path = parent.getProperty("webmail.data.path") + System.getProperty("file.separator") + domain + System.getProperty("file.separator"); File f = new File(path); if (f.canRead() && f.isDirectory()) { final String[] files = f.list(new FilenameFilter() { public boolean accept(File file, String s) { if (s.endsWith(".xml")) { return true; } else { return false; } } }); return new Enumeration() { int i = 0; public boolean hasMoreElements() { return i < files.length; } public Object nextElement() { int cur = i++; return files[cur].substring(0, files[cur].length() - 4); } }; } else { log.warn("SimpleStorage: Could not list files in directory " + path); return new Enumeration() { public boolean hasMoreElements() { return false; } public Object nextElement() { return null; } }; } } public XMLUserData createUserData(String user, String domain, String password) throws CreateUserDataException { XMLUserData data; String template = parent.getProperty("webmail.xml.path") + System.getProperty("file.separator") + "userdata.xml"; File f = new File(template); if (!f.exists()) { log.warn("SimpleStorage: User configuration template (" + template + ") doesn't exist!"); throw new CreateUserDataException("User configuration template (" + template + ") doesn't exist!", user, domain); } else if (!f.canRead()) { log.warn("SimpleStorage: User configuration template (" + template + ") is not readable!"); throw new CreateUserDataException("User configuration template (" + template + ") is not readable!", user, domain); } Document root; try { DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); root = parser.parse("file://" + template); data = new XMLUserData(root); data.init(user, domain, password); if (getConfig("SHOW ADVERTISEMENTS").toUpperCase().equals("YES")) { if (user.indexOf("@") != -1) { data.setSignature(user + "\n\n" + getConfig("ADVERTISEMENT MESSAGE")); } else { data.setSignature(user + "@" + domain + "\n\n" + getConfig("ADVERTISEMENT MESSAGE")); } } else { if (user.indexOf("@") != -1) { data.setSignature(user); } else { data.setSignature(user + "@" + domain); } } data.setTheme(parent.getDefaultTheme()); WebMailVirtualDomain vdom = getVirtualDomain(domain); data.addMailHost("Default", getConfig("DEFAULT PROTOCOL") + "://" + vdom.getDefaultServer(), user, password, vdom.getImapBasedir()); } catch (Exception ex) { log.warn("SimpleStorage: User configuration template (" + template + ") exists but could not be parsed", ex); throw new CreateUserDataException( "User configuration template (" + template + ") exists but could not be parsed", user, domain); } return data; } /** * @see net.wastl.webmail.server.Storage.getUserData() */ public XMLUserData getUserData(String user, String domain, String password, boolean authenticate) throws UserDataException, InvalidPasswordException { if (authenticate) { auth.authenticatePreUserData(user, domain, password); } if (user.equals("")) { return null; } XMLUserData data = (XMLUserData) user_cache.get(user + user_domain_separator + domain); if (data == null) { user_cache.miss(); String filename = parent.getProperty("webmail.data.path") + System.getProperty("file.separator") + domain + System.getProperty("file.separator") + user + ".xml"; boolean error = true; File f = new File(filename); if (f.exists() && f.canRead()) { log.info("SimpleStorage: Reading user configuration (" + f.getAbsolutePath() + ") for " + user); long t_start = System.currentTimeMillis(); try { DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document root = parser .parse(new InputSource(new InputStreamReader(new FileInputStream(filename), "UTF-8"))); // Document root = parser.parse(new InputSource(new InputStreamReader(new FileInputStream(f.getAbsolutePath()), "UTF-8"))); data = new XMLUserData(root); log.debug("SimpleStorage: Parsed Document " + root); error = false; } catch (Exception ex) { log.warn("SimpleStorage: User configuration for " + user + " exists but could not be parsed (" + ex.getMessage() + ")", ex); error = true; } long t_end = System.currentTimeMillis(); log.debug("SimpleStorage: Parsing of XML userdata for " + user + ", domain " + domain + " took " + (t_end - t_start) + "ms."); if (authenticate) { auth.authenticatePostUserData(data, domain, password); } } if (error && !f.exists()) { log.info("UserConfig: Creating user configuration for " + user); data = createUserData(user, domain, password); error = false; if (authenticate) { auth.authenticatePostUserData(data, domain, password); } } if (error) { log.error("UserConfig: Could not read userdata for " + user + "!"); throw new UserDataException("Could not read userdata!", user, domain); } user_cache.put(user + user_domain_separator + domain, data); } else { user_cache.hit(); if (authenticate) { auth.authenticatePostUserData(data, domain, password); } } return data; } public void saveUserData(String user, String domain) { try { String path = parent.getProperty("webmail.data.path") + System.getProperty("file.separator") + domain; File p = new File(path); if ((p.exists() && p.isDirectory()) || p.mkdirs()) { File f = new File(path + System.getProperty("file.separator") + user + ".xml"); if ((!f.exists() && p.canWrite()) || f.canWrite()) { XMLUserData userdata = getUserData(user, domain, "", false); Document d = userdata.getRoot(); long t_start = System.currentTimeMillis(); FileOutputStream out = new FileOutputStream(f); // XMLCommon.writeXML(d,out,parent.getProperty("webmail.xml.path")+ // System.getProperty("file.separator")+"userdata.dtd"); XMLCommon.writeXML(d, out, "file://" + parent.getProperty("webmail.xml.path") + System.getProperty("file.separator") + "userdata.dtd"); out.flush(); out.close(); long t_end = System.currentTimeMillis(); log.debug("SimpleStorage: Serializing userdata for " + user + ", domain " + domain + " took " + (t_end - t_start) + "ms."); } else { log.warn("SimpleStorage: Could not write userdata (" + f.getAbsolutePath() + ") for user " + user); } } else { log.error("SimpleStorage: Could not create path " + path + ". Aborting with user " + user); } } catch (Exception ex) { log.error("SimpleStorage: Unexpected error while trying to save user configuration " + "for user " + user + "(" + ex.getMessage() + ").", ex); } } /** * Delete a WebMail user * @param user Name of the user to delete */ public void deleteUserData(String user, String domain) { String path = parent.getProperty("webmail.data.path") + System.getProperty("file.separator") + domain + System.getProperty("file.separator") + user + ".xml"; File f = new File(path); if (!f.canWrite() || !f.delete()) { log.error("SimpleStorage: Could not delete user " + user + " (" + path + ")!"); } else { log.info("SimpleStorage: Deleted user " + user + "!"); } user_cache.remove(user + user_domain_separator + domain); } public String toString() { String s = "SimpleStorage:\n" + super.toString(); s += " - user cache: Capacity " + user_cache.getCapacity() + ", Usage " + user_cache.getUsage(); s += ", " + user_cache.getHits() + " hits, " + user_cache.getMisses() + " misses\n"; return s; } }