001:/* CVS ID: $Id: WebMailServer.java,v 1.2 2002/10/03 19:44:32 wastl Exp $ */
002:package net.wastl.webmail.server;
003:
004:import java.net.*;
005:import java.io.*;
006:import java.util.*;
007:import java.lang.reflect.*;
008:
009:import javax.mail.Session;
010:import javax.mail.Provider;
011:
012:import net.wastl.webmail.debug.ErrorHandler;
013:import net.wastl.webmail.server.http.*;
014:import net.wastl.webmail.config.ConfigScheme;
015:import net.wastl.webmail.misc.Helper;
016:import net.wastl.webmail.exceptions.*;
017:
018:/*
019: * WebMailServer.java
020: *
021: * Created: Tue Feb 2 12:07:25 1999
022: *
023: * Copyright (C) 1999-2000 Sebastian Schaffert
024: *
025: * This program is free software; you can redistribute it and/or
026: * modify it under the terms of the GNU General Public License
027: * as published by the Free Software Foundation; either version 2
028: * of the License, or (at your option) any later version.
029: *
030: * This program is distributed in the hope that it will be useful,
031: * but WITHOUT ANY WARRANTY; without even the implied warranty of
032: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
033: * GNU General Public License for more details.
034: *
035: * You should have received a copy of the GNU General Public License
036: * along with this program; if not, write to the Free Software
037: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
038: */
039:/**
040: * This is WebMails main server. From here most parts will be administered.
041: *
042: * @author Sebastian Schaffert
043: * @version $Revision: 1.2 $
044: */
045:/* 9/24/2000 devink - Updated for new challenge/response auth */
046:public abstract class WebMailServer {
047:
048: protected ConnectionTimer timer;
049:
050: protected AuthenticatorHandler ahandler;
051: protected PluginHandler phandler;
052: protected ToplevelURLHandler uhandler;
053:
054: protected Hashtable sessions;
055:
056: protected static boolean debug=@debug@;
057:
058:
059: public static final String VERSION="@version@";
060:
061: protected static Provider[] possible_providers;
062: protected static Provider[] store_providers;
063: protected static Provider[] transport_providers;
064:
065: private long start_time;
066:
067: protected static Storage storage;
068: protected ConfigScheme config_scheme;
069:
070: protected static WebMailServer server;
071:
072: protected Properties config;
073:
074: // Modified by exce, start.
075: /**
076: * Webmail default locale setting.
077: */
078: protected static Locale defaultLocale = null;
079: // Modified by exce, end.
080:
081:
082: protected static String defaultTheme = null;
083:
084: public WebMailServer() {
085: }
086:
087: /**
088: * If debugging is enabled, send the given message to STDERR.
089: *
090: * @param msg The message
091: */
092: public static void debugOut(String msg) {
093: if(getDebug()) {
094: System.err.println("DBG: "+msg);
095: }
096: }
097:
098: /**
099: * If debugging is enabled, send the given exception together with an explanatory message
100: * to STDERR.
101: *
102: * @param msg The explanatory message
103: * @param ex The exception
104: */
105: public void debugOut(String msg, Exception ex) {
106: if(getDebug()) {
107: System.err.println("DBG: "+msg);
108: ex.printStackTrace();
109: }
110: }
111:
112: public static boolean getDebug() {
113: return debug;
114: }
115:
116: public static void setDebug(boolean b) {
117: debug=b;
118: }
119:
120:
121: protected void doInit() throws WebMailException {
122: server=this ;
123: System.err.println("\n\nWebMail/Java Server v"+VERSION+" going up...");
124: System.err.println("=====================================\n");
125: System.err.println("Initalizing...");
126:
127: new SystemCheck(this );
128:
129: initConfig();
130: // Modified by exce, start
131: /**
132: * Initialize the default locale for webmail.
133: */
134: if ((config.getProperty("webmail.default.locale.language") == null) ||
135: (config.getProperty("webmail.default.locale.country") == null))
136: defaultLocale = Locale.getDefault();
137: else
138: defaultLocale = new Locale(
139: config.getProperty("webmail.default.locale.language"),
140: config.getProperty("webmail.default.locale.country")
141: );
142: System.err.println("- Default Locale: " + defaultLocale.getDisplayName());
143: // Modified by exce, end
144:
145: /*
146: * Set the default theme to the parameter given in webmail.default.theme
147: * or to "bibop" if unset.
148: */
149: if(config.getProperty("webmail.default.theme")==null) {
150: defaultTheme="bibop";
151: } else {
152: defaultTheme=config.getProperty("webmail.default.theme");
153: }
154: System.err.println("- Default Theme: " + defaultTheme);
155:
156: ahandler=new AuthenticatorHandler(this );
157:
158: System.err.println("- Storage API ("+System.getProperty("webmail.storage")+
159: ") and Configuration ... ");
160:
161: initStorage();
162: storage.log(Storage.LOG_CRIT,"=============================== cut ===============================");
163: storage.log(Storage.LOG_CRIT,"Storage initialized.");
164:
165: timer=new ConnectionTimer();
166: sessions=new Hashtable();
167:
168: System.err.println(" done!");
169:
170: uhandler=new ToplevelURLHandler(this );
171:
172: storage.log(Storage.LOG_CRIT,"URLHandler initialized.");
173:
174: phandler=new PluginHandler(this );
175:
176: storage.log(Storage.LOG_CRIT,"Plugins initialized.");
177:
178: initProviders();
179:
180: initServers();
181:
182: storage.initConfigKeys();
183:
184: storage.log(Storage.LOG_CRIT,"=============================== cut ===============================");
185: storage.log(Storage.LOG_CRIT,"WebMail/Java Server "+VERSION+" initialization completed.");
186: System.err.println("Initalization complete.");
187: start_time=System.currentTimeMillis();
188:
189: }
190:
191: protected void initStorage() {
192: /* Storage API */
193: try {
194: Class storage_api=Class.forName(config.getProperty("webmail.storage"));
195:
196: Class[] tmp=new Class[1];
197: tmp[0]=Class.forName("net.wastl.webmail.server.WebMailServer");
198: Constructor cons=storage_api.getConstructor(tmp);
199:
200: Object[] sargs=new Object[1];
201: sargs[0]=this ;
202:
203: storage=(Storage)cons.newInstance(sargs);
204:
205: } catch(InvocationTargetException e) {
206: Throwable t=e.getTargetException();
207: System.err.println("Nested exception: ");
208: t.printStackTrace();
209: System.err.println("Fatal error. Could not initialize. Exiting now!");
210: System.exit(1);
211: } catch(Exception e) {
212: e.printStackTrace();
213: System.err.println("Fatal error. Could not initialize. Exiting now!");
214: System.exit(1);
215: }
216: }
217:
218: protected void initConfig() {
219: config_scheme=new ConfigScheme();
220:
221: config_scheme.configRegisterIntegerKey("SESSION TIMEOUT","3600000",
222: "Timeout in milliseconds after which a WebMailSession is closed automatically.");
223: config_scheme.configRegisterCryptedStringKey("ADMIN PASSWORD","Secret",
224: "Password for administrator connections. Shown encrypted, but enter"+
225: " plain password to change.");
226:
227: }
228:
229:
230: protected void initProviders() {
231: possible_providers=Session.getDefaultInstance(System.getProperties(),null).getProviders();
232: System.err.println("- Mail providers:");
233: config_scheme.configRegisterChoiceKey("DEFAULT PROTOCOL","Protocol to be used as default");
234: int p_transport=0;
235: int p_store=0;
236: for(int i=0; i<possible_providers.length;i++) {
237: System.err.println(" * "+possible_providers[i].getProtocol()+" from "+possible_providers[i].getVendor());
238: if(possible_providers[i].getType() == Provider.Type.STORE) {
239: p_store++;
240: config_scheme.configAddChoice("DEFAULT PROTOCOL",possible_providers[i].getProtocol(),"Use "+
241: possible_providers[i].getProtocol()+" from "+possible_providers[i].getVendor());
242: config_scheme.configRegisterYesNoKey("ENABLE "+possible_providers[i].getProtocol().toUpperCase(),"Enable "+
243: possible_providers[i].getProtocol()+" from "+possible_providers[i].getVendor());
244: } else {
245: p_transport++;
246: }
247: }
248: store_providers=new Provider[p_store];
249: transport_providers=new Provider[p_transport];
250: p_store=0;
251: p_transport=0;
252: for(int i=0; i<possible_providers.length;i++) {
253: if(possible_providers[i].getType() == Provider.Type.STORE) {
254: store_providers[p_store]=possible_providers[i];
255: p_store++;
256: } else {
257: transport_providers[p_transport]=possible_providers[i];
258: p_transport++;
259: }
260: }
261: /* We want to use IMAP as default, since this is the most useful protocol for WebMail */
262: config_scheme.setDefaultValue("DEFAULT PROTOCOL","imap");
263: }
264:
265:
266: /**
267: * Init possible servers of this main class
268: */
269: protected abstract void initServers();
270:
271: protected abstract void shutdownServers();
272:
273: public abstract Object getServer(String ID);
274:
275: public abstract Enumeration getServers();
276:
277: public String getBasePath() {
278: return "";
279: }
280:
281: public String getImageBasePath() {
282: return "";
283: }
284:
285:
286: public abstract void reinitServer(String ID);
287:
288:
289: public String getBaseURI(HTTPRequestHeader header) {
290: String host=header.getHeader("Host");
291: StringTokenizer tok=new StringTokenizer(host,":");
292: String hostname=tok.nextToken();
293: int port=80;
294: if(tok.hasMoreElements()) {
295: try {
296: port=Integer.parseInt(tok.nextToken());
297: } catch(NumberFormatException e) {}
298: }
299: int ssl_port=443;
300: try {
301: ssl_port=Integer.parseInt(storage.getConfig("ssl port"));
302: } catch(NumberFormatException e) {}
303: int http_port=80;
304: try {
305: http_port=Integer.parseInt(storage.getConfig("http port"));
306: } catch(NumberFormatException e) {}
307: String protocol="http";
308: if(port==ssl_port) protocol="https"; else
309: if(port==http_port) protocol="http";
310: return protocol+"://"+host;
311: }
312:
313: public Provider[] getStoreProviders() {
314: Vector v=new Vector();
315: for(int i=0;i<store_providers.length;i++) {
316: if(storage.getConfig("ENABLE "+store_providers[i].getProtocol().toUpperCase()).equals("YES")) {
317: v.addElement(store_providers[i]);
318: }
319: }
320: Provider[] retval=new Provider[v.size()];
321: v.copyInto(retval);
322: return retval;
323: }
324:
325: public Provider[] getTransportProviders() {
326: return transport_providers;
327: }
328:
329: public ConnectionTimer getConnectionTimer() {
330: return timer;
331: }
332:
333:
334: public static Storage getStorage() {
335: return storage;
336: }
337:
338: public PluginHandler getPluginHandler() {
339: return phandler;
340: }
341:
342: public AuthenticatorHandler getAuthenticatorHandler() {
343: return ahandler;
344: }
345:
346: public ToplevelURLHandler getURLHandler() {
347: return uhandler;
348: }
349:
350: public ConfigScheme getConfigScheme() {
351: return config_scheme;
352: }
353:
354:
355:
356: public String getProperty(String name) {
357: return config.getProperty(name);
358: }
359:
360: public static String getDefaultTheme() {
361: return defaultTheme;
362: }
363:
364: // Modified by exce, start
365: /**
366: * Return default locale.
367: *
368: * Related code:
369: * 1. login screen:
370: * server/TopLevelHandler.java line #110.
371: * 2. webmail.css:
372: * plugins/PassThroughPlugin.java line #77.
373: * 3. user's default locale setting:
374: * xml/XMLUserData.java line #82.
375: *
376: * @return default locale.
377: */
378: public static Locale getDefaultLocale() {
379: return defaultLocale;
380: }
381: // Modified by exce, end
382:
383: public void setProperty(String name, String value) {
384: config.put(name,value);
385: }
386:
387: /**
388: @deprecated Use StorageAPI instead
389: */
390: public static String getConfig(String key) {
391: return storage.getConfig(key);
392: }
393:
394: public void restart() {
395: System.err.println("Initiating shutdown for child processes:");
396: Enumeration e=sessions.keys();
397: System.err.print("- Removing active WebMail sessions ... ");
398: while(e.hasMoreElements()) {
399: HTTPSession w=(HTTPSession)sessions.get(e.nextElement());
400: removeSession(w);
401: }
402: System.err.println("done!");
403: shutdownServers();
404: try {
405: Thread.sleep(5000);
406: } catch(Exception ex) {}
407: storage.log(Storage.LOG_CRIT,"Shutdown completed successfully. Restarting.");
408: storage.shutdown();
409: System.err.println("Garbage collecting ...");
410: System.gc();
411: try {
412: doInit();
413: } catch(WebMailException ex) {
414: ex.printStackTrace();
415: System.exit(1);
416: }
417: }
418:
419: public void shutdown() {
420: System.err.println("Initiating shutdown for child processes:");
421: Enumeration e=sessions.keys();
422: System.err.print("- Removing active WebMail sessions ... ");
423: while(e.hasMoreElements()) {
424: HTTPSession w=(HTTPSession)sessions.get(e.nextElement());
425: removeSession(w);
426: }
427: System.err.println("done!");
428: shutdownServers();
429: storage.log(Storage.LOG_CRIT,"Shutdown completed successfully. Terminating.");
430: storage.shutdown();
431: System.err.println("Shutdown complete! Will return to console now.");
432: System.exit(0);
433: }
434:
435: public long getUptime() {
436: return System.currentTimeMillis()-start_time;
437: }
438:
439: public static String getVersion() {
440: return "WebMail/Java v"+VERSION+", built with JDK @java-version@";
441: }
442:
443: public static String getCopyright() {
444: return "(c)1999-@year@ Sebastian Schaffert and others";
445: }
446:
447: public static WebMailServer getServer() {
448: return server;
449: }
450:
451: public static String generateMessageID(String user) {
452: long time=System.currentTimeMillis();
453: String msgid=Long.toHexString(time)+".JavaWebMail."+VERSION+"."+user;
454: try {
455: msgid+="@"+InetAddress.getLocalHost().getHostName();
456: } catch(Exception ex){}
457: return msgid;
458: }
459:
460: public void removeSession(HTTPSession w) {
461: storage.log(Storage.LOG_INFO,"Removing session: "+w.getSessionCode());
462: timer.removeTimeableConnection(w);
463: sessions.remove(w.getSessionCode());
464: if(!w.isLoggedOut()) {
465: w.logout();
466: }
467: }
468:
469: public HTTPSession getSession(String key) {
470: return (HTTPSession)sessions.get(key);
471: }
472:
473:
474: public Enumeration getSessions() {
475: return sessions.keys();
476: }
477:
478:} // WebMailServer
|