001: /* CVS ID: $Id: SimpleStorage.java,v 1.1.1.1 2002/10/02 18:42:54 wastl Exp $ */
002: package net.wastl.webmail.storage.simple;
003:
004: import java.io.*;
005: import java.text.*;
006: import java.util.*;
007: import java.util.zip.*;
008: import net.wastl.webmail.storage.*;
009: import net.wastl.webmail.server.*;
010: import net.wastl.webmail.config.*;
011: import net.wastl.webmail.misc.*;
012: import net.wastl.webmail.xml.*;
013: import net.wastl.webmail.exceptions.*;
014:
015: //import org.apache.xml.serialize.*;
016: import org.w3c.dom.*;
017:
018: import javax.xml.parsers.*;
019:
020: // Modified by exce, start
021: import org.xml.sax.InputSource;
022:
023: // Modified by exce, end
024:
025: /**
026: * SimpleStorage.java
027: *
028: * Created: Feb 1999
029: *
030: * Copyright (C) 1999-2000 Sebastian Schaffert
031: *
032: * This program is free software; you can redistribute it and/or
033: * modify it under the terms of the GNU General Public License
034: * as published by the Free Software Foundation; either version 2
035: * of the License, or (at your option) any later version.
036: *
037: * This program is distributed in the hope that it will be useful,
038: * but WITHOUT ANY WARRANTY; without even the implied warranty of
039: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
040: * GNU General Public License for more details.
041: *
042: * You should have received a copy of the GNU General Public License
043: * along with this program; if not, write to the Free Software
044: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
045: */
046:
047: /**
048: * This is the SimpleStorage class for the non-enterprise edition of WebMail.
049: * It provides means of getting and storing data in ZIPFiles and
050: * ResourceBundles.
051: *
052: * @see net.wastl.webmail.server.Storage
053: * @author Sebastian Schaffert
054: * @versin $Revision: 1.1.1.1 $
055: */
056: public class SimpleStorage extends FileStorage {
057:
058: public static final String user_domain_separator = "|";
059:
060: protected Hashtable resources;
061:
062: protected Hashtable vdoms;
063:
064: protected ExpireableCache user_cache;
065:
066: protected int user_cache_size = 100;
067:
068: /**
069: * Initialize SimpleStorage.
070: * Fetch Configuration Information etc.
071: */
072: public SimpleStorage(WebMailServer parent) {
073: super (parent);
074: saveXMLSysData();
075: }
076:
077: protected void initConfig() {
078: System.err.print(" * Configuration ... ");
079:
080: loadXMLSysData();
081:
082: System.err
083: .println("successfully parsed XML configuration file.");
084:
085: }
086:
087: protected void loadXMLSysData() {
088: String datapath = parent.getProperty("webmail.data.path");
089: String file = "file://" + datapath
090: + System.getProperty("file.separator") + "webmail.xml";
091: // String file=datapath+System.getProperty("file.separator")+"webmail.xml";
092: // bug fixed by Christian Senet
093: Document root;
094: try {
095: DocumentBuilder parser = DocumentBuilderFactory
096: .newInstance().newDocumentBuilder();
097: root = parser.parse(file);
098: if (debug)
099: System.err
100: .println("\nConfiguration file parsed, document: "
101: + root);
102: sysdata = new XMLSystemData(root, cs);
103: log(Storage.LOG_DEBUG,
104: "SimpleStorage: WebMail configuration loaded.");
105: } catch (Exception ex) {
106: log(Storage.LOG_ERR,
107: "SimpleStorage: Failed to load WebMail configuration file. Reason: "
108: + ex.getMessage());
109: ex.printStackTrace();
110: System.exit(0);
111: }
112:
113: }
114:
115: protected void saveXMLSysData() {
116: try {
117: Document d = sysdata.getRoot();
118: OutputStream cfg_out = new FileOutputStream(parent
119: .getProperty("webmail.data.path")
120: + System.getProperty("file.separator")
121: + "webmail.xml");
122:
123: XMLCommon.writeXML(d, cfg_out, "file://"
124: + parent.getProperty("webmail.xml.path")
125: + System.getProperty("file.separator")
126: + "sysdata.dtd");
127:
128: // XMLCommon.writeXML(d,cfg_out,parent.getProperty("webmail.xml.path")+
129: // System.getProperty("file.separator")+"sysdata.dtd");
130: cfg_out.flush();
131: cfg_out.close();
132: sysdata.setLoadTime(System.currentTimeMillis());
133: log(Storage.LOG_DEBUG,
134: "SimpleStorage: WebMail configuration saved.");
135: } catch (Exception ex) {
136: log(Storage.LOG_ERR,
137: "SimpleStorage: Error while trying to save WebMail configuration ("
138: + ex.getMessage() + ").");
139: ex.printStackTrace();
140: }
141: }
142:
143: protected void initCache() {
144: // Initialize the file cache from FileStorage
145: super .initCache();
146:
147: // Now initialize the user cache
148: cs.configRegisterIntegerKey(this , "CACHE SIZE USER", "100",
149: "Size of the user cache");
150: try {
151: // Default value 100, if parsing fails.
152: user_cache_size = 100;
153: user_cache_size = Integer
154: .parseInt(getConfig("CACHE SIZE USER"));
155: } catch (NumberFormatException e) {
156: }
157: if (user_cache == null) {
158: user_cache = new ExpireableCache(user_cache_size);
159: } else {
160: user_cache.setCapacity(user_cache_size);
161: }
162: }
163:
164: public Enumeration getUsers(String domain) {
165: String path = parent.getProperty("webmail.data.path")
166: + System.getProperty("file.separator") + domain
167: + System.getProperty("file.separator");
168:
169: File f = new File(path);
170: if (f.canRead() && f.isDirectory()) {
171: final String[] files = f.list(new FilenameFilter() {
172: public boolean accept(File file, String s) {
173: if (s.endsWith(".xml")) {
174: return true;
175: } else {
176: return false;
177: }
178: }
179: });
180: return new Enumeration() {
181: int i = 0;
182:
183: public boolean hasMoreElements() {
184: return i < files.length;
185: }
186:
187: public Object nextElement() {
188: int cur = i++;
189: return files[cur].substring(0,
190: files[cur].length() - 4);
191: }
192: };
193: } else {
194: log(Storage.LOG_WARN,
195: "SimpleStorage: Could not list files in directory "
196: + path);
197: return new Enumeration() {
198: public boolean hasMoreElements() {
199: return false;
200: }
201:
202: public Object nextElement() {
203: return null;
204: }
205: };
206: }
207: }
208:
209: public XMLUserData createUserData(String user, String domain,
210: String password) throws CreateUserDataException {
211: XMLUserData data;
212: String template = parent.getProperty("webmail.xml.path")
213: + System.getProperty("file.separator") + "userdata.xml";
214:
215: File f = new File(template);
216: if (!f.exists()) {
217: log(Storage.LOG_WARN,
218: "SimpleStorage: User configuration template ("
219: + template + ") doesn't exist!");
220: throw new CreateUserDataException(
221: "User configuration template (" + template
222: + ") doesn't exist!", user, domain);
223: } else if (!f.canRead()) {
224: log(Storage.LOG_WARN,
225: "SimpleStorage: User configuration template ("
226: + template + ") is not readable!");
227: throw new CreateUserDataException(
228: "User configuration template (" + template
229: + ") is not readable!", user, domain);
230: }
231:
232: Document root;
233: try {
234: DocumentBuilder parser = DocumentBuilderFactory
235: .newInstance().newDocumentBuilder();
236: root = parser.parse("file://" + template);
237: data = new XMLUserData(root);
238: data.init(user, domain, password);
239: if (getConfig("SHOW ADVERTISEMENTS").toUpperCase().equals(
240: "YES")) {
241: if (domain.equals("")) {
242: data.setSignature(user + "\n\n"
243: + getConfig("ADVERTISEMENT MESSAGE"));
244: } else {
245: data.setSignature(user + "@" + domain + "\n\n"
246: + getConfig("ADVERTISEMENT MESSAGE"));
247: }
248: } else {
249: if (domain.equals("")) {
250: data.setSignature(user);
251: } else {
252: data.setSignature(user + "@" + domain);
253: }
254: }
255: data.setTheme(parent.getDefaultTheme());
256: WebMailVirtualDomain vdom = getVirtualDomain(domain);
257: data.addMailHost("Default", getConfig("DEFAULT PROTOCOL")
258: + "://" + vdom.getDefaultServer(), user, password);
259:
260: } catch (Exception ex) {
261: log(Storage.LOG_WARN,
262: "SimpleStorage: User configuration template ("
263: + template
264: + ") exists but could not be parsed");
265: if (debug)
266: ex.printStackTrace();
267: throw new CreateUserDataException(
268: "User configuration template (" + template
269: + ") exists but could not be parsed", user,
270: domain);
271: }
272: return data;
273: }
274:
275: /**
276: * @see net.wastl.webmail.server.Storage.getUserData()
277: *
278: * devink 7/15/2000 - Added TwoPassAuthenticationException
279: * - changed to doAuth*UserData()
280: * - Added challenged arg.
281: * 9/24/2000 - reverted to old getUserData for new cr auth
282: */
283: public XMLUserData getUserData(String user, String domain,
284: String password, boolean authenticate)
285: throws UserDataException, InvalidPasswordException {
286: if (authenticate) {
287: auth.authenticatePreUserData(user, domain, password);
288: }
289:
290: if (user.equals("")) {
291: return null;
292: }
293:
294: XMLUserData data = (XMLUserData) user_cache.get(user
295: + user_domain_separator + domain);
296: if (data == null) {
297: user_cache.miss();
298: String filename = parent.getProperty("webmail.data.path")
299: + System.getProperty("file.separator") + domain
300: + System.getProperty("file.separator") + user
301: + ".xml";
302: boolean error = true;
303: File f = new File(filename);
304: if (f.exists() && f.canRead()) {
305: log(Storage.LOG_INFO,
306: "SimpleStorage: Reading user configuration ("
307: + f.getAbsolutePath() + ") for " + user);
308:
309: long t_start = System.currentTimeMillis();
310: try {
311: DocumentBuilder parser = DocumentBuilderFactory
312: .newInstance().newDocumentBuilder();
313: Document root = parser.parse(new InputSource(
314: new InputStreamReader(new FileInputStream(
315: filename), "UTF-8")));
316: // Document root = parser.parse(new InputSource(new InputStreamReader(new FileInputStream(f.getAbsolutePath()), "UTF-8")));
317:
318: data = new XMLUserData(root);
319: if (debug)
320: System.err
321: .println("SimpleStorage: Parsed Document "
322: + root);
323: error = false;
324: } catch (Exception ex) {
325: log(
326: Storage.LOG_WARN,
327: "SimpleStorage: User configuration for "
328: + user
329: + " exists but could not be parsed ("
330: + ex.getMessage() + ")");
331: if (debug)
332: ex.printStackTrace();
333: error = true;
334: }
335: long t_end = System.currentTimeMillis();
336: log(Storage.LOG_DEBUG,
337: "SimpleStorage: Parsing of XML userdata for "
338: + user + ", domain " + domain
339: + " took " + (t_end - t_start) + "ms.");
340:
341: if (authenticate) {
342: auth.authenticatePostUserData(data, domain,
343: password);
344: }
345: }
346:
347: if (error && !f.exists()) {
348: log(Storage.LOG_INFO,
349: "UserConfig: Creating user configuration for "
350: + user);
351:
352: data = createUserData(user, domain, password);
353:
354: error = false;
355:
356: if (authenticate) {
357: auth.authenticatePostUserData(data, domain,
358: password);
359: }
360: }
361: if (error) {
362: log(Storage.LOG_ERR,
363: "UserConfig: Could not read userdata for "
364: + user + "!");
365: throw new UserDataException("Could not read userdata!",
366: user, domain);
367: }
368: user_cache.put(user + user_domain_separator + domain, data);
369: } else {
370: user_cache.hit();
371: if (authenticate) {
372: auth.authenticatePostUserData(data, domain, password);
373: }
374: }
375:
376: return data;
377: }
378:
379: public void saveUserData(String user, String domain) {
380: try {
381:
382: String path = parent.getProperty("webmail.data.path")
383: + System.getProperty("file.separator") + domain;
384: File p = new File(path);
385: if ((p.exists() && p.isDirectory()) || p.mkdirs()) {
386: File f = new File(path
387: + System.getProperty("file.separator") + user
388: + ".xml");
389: if ((!f.exists() && p.canWrite()) || f.canWrite()) {
390: XMLUserData userdata = getUserData(user, domain,
391: "", false);
392: Document d = userdata.getRoot();
393:
394: long t_start = System.currentTimeMillis();
395:
396: FileOutputStream out = new FileOutputStream(f);
397: // XMLCommon.writeXML(d,out,parent.getProperty("webmail.xml.path")+
398: // System.getProperty("file.separator")+"userdata.dtd");
399:
400: XMLCommon.writeXML(d, out, "file://"
401: + parent.getProperty("webmail.xml.path")
402: + System.getProperty("file.separator")
403: + "userdata.dtd");
404: out.flush();
405: out.close();
406: long t_end = System.currentTimeMillis();
407: log(Storage.LOG_DEBUG,
408: "SimpleStorage: Serializing userdata for "
409: + user + ", domain " + domain
410: + " took " + (t_end - t_start)
411: + "ms.");
412: } else {
413: log(Storage.LOG_WARN,
414: "SimpleStorage: Could not write userdata ("
415: + f.getAbsolutePath()
416: + ") for user " + user);
417: }
418: } else {
419: log(Storage.LOG_ERR,
420: "SimpleStorage: Could not create path " + path
421: + ". Aborting with user " + user);
422: }
423: } catch (Exception ex) {
424: log(Storage.LOG_ERR,
425: "SimpleStorage: Unexpected error while trying to save user configuration "
426: + "for user " + user + "("
427: + ex.getMessage() + ").");
428: if (debug)
429: ex.printStackTrace();
430: }
431: }
432:
433: /**
434: * Delete a WebMail user
435: * @param user Name of the user to delete
436: */
437: public void deleteUserData(String user, String domain) {
438: String path = parent.getProperty("webmail.data.path")
439: + System.getProperty("file.separator") + domain
440: + System.getProperty("file.separator") + user + ".xml";
441: File f = new File(path);
442: if (!f.canWrite() || !f.delete()) {
443: log(Storage.LOG_ERR,
444: "SimpleStorage: Could not delete user " + user
445: + " (" + path + ")!");
446: } else {
447: log(Storage.LOG_INFO, "SimpleStorage: Deleted user " + user
448: + "!");
449: }
450: user_cache.remove(user + user_domain_separator + domain);
451: }
452:
453: public String toString() {
454: String s = "SimpleStorage:\n" + super .toString();
455: s += " - user cache: Capacity " + user_cache.getCapacity()
456: + ", Usage " + user_cache.getUsage();
457: s += ", " + user_cache.getHits() + " hits, "
458: + user_cache.getMisses() + " misses\n";
459: return s;
460: }
461:
462: }
|