Source code: org/mrbook/mrpostman/MrPostman.java
1 /*
2 * -*- mode: java; c-basic-indent: 4; indent-tabs-mode: nil -*-
3 * :indentSize=4:noTabs=true:tabSize=4:indentOnTab=true:indentOnEnter=true:mode=java:
4 * ex: set tabstop=4 expandtab:
5 *
6 * MrPostman - webmail <-> email gateway
7 * Copyright (C) 2002-2003 MrPostman Development Group
8 * Projectpage: http://mrbook.org/mrpostman/
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 * In particular, this implies that users are responsible for
21 * using MrPostman after reading the terms and conditions given
22 * by their web-mail provider.
23 *
24 * You should have received a copy of the GNU General Public License
25 * Named LICENSE in the base directory of this distribution,
26 * if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 */
29
30 package org.mrbook.mrpostman;
31
32 import org.mrbook.mrpostman.gui.MrPostmanGui;
33 import org.mrbook.mrpostman.help.HelpServer;
34 import org.mrbook.mrpostman.pop.PopServer;
35
36 import java.io.BufferedReader;
37 import java.io.IOException;
38 import java.io.InputStreamReader;
39 import java.io.OutputStreamWriter;
40 import java.io.PrintWriter;
41
42 import java.net.Socket;
43
44 import java.util.HashMap;
45 import java.util.Iterator;
46 import java.util.Vector;
47 import java.util.logging.Level;
48 import java.util.logging.Logger;
49 import java.util.prefs.Preferences;
50
51 import javax.swing.JOptionPane;
52
53
54 public class MrPostman {
55 public static final String CVSID = "$Id: MrPostman.java,v 1.19 2003/04/24 22:30:32 lbruand Exp $";
56 private static Logger logger = Logger.getLogger("org.mrbook.mrpostman.MrPostman");
57 public static int DEFAULT_PORT = 11110;
58 public static int DEFAULT_HELP_PORT = 22220;
59 public static boolean DEFAULT_START_LOG = false;
60 private static MrPostman maininstance = null;
61 private static HelpServer hs = null;
62 public Preferences userprefs = null;
63 private boolean serverRunning = false;
64 private PopServer pops = null;
65 private MrPostmanGui gui = null;
66 private Vector modulesVector = null;
67 private int helpPort = 0;
68
69 MrPostman() {
70 int port = 0;
71 maininstance = this;
72 initPrefs();
73 port = getPropertyInt("ServerPort", DEFAULT_PORT);
74 initModules();
75
76 try {
77 pops = new PopServer(port);
78
79 serverRunning = true;
80 } catch (Exception e) {
81 // Before showing an error, try to connect to localhost on
82 // that port and issue the GUI command.
83 try {
84 Socket s = new Socket("127.0.0.1", port);
85 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
86 PrintWriter pr = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
87 pr.print("GUI\n");
88 pr.flush();
89 logger.info("Port " + port + " already in use. Sent GUI command to (assumed) current MrPostman process");
90 br.readLine();
91 String str = br.readLine();
92
93 if (str.startsWith("+OK")) {
94 logger.info("Received an OK from server. Quitting.");
95 }
96 System.exit(0);
97 } catch (Exception exc) {
98 String msg = new String("Unable to start server on port " + port);
99
100 // There might be something already running on that port.
101 logger.severe(msg);
102 JOptionPane.showMessageDialog(null, msg, "Error", JOptionPane.WARNING_MESSAGE);
103 System.exit(1);
104 }
105 }
106
107 // The server has been started succesfully, now bring up the gui
108 if (getPropertyBool("RunGuiStart", true)) {
109 logger.info("Starting gui according to preferences");
110 showGui();
111 } else {
112 logger.info("NOT Starting gui according to preferences");
113 }
114 }
115
116 private void initPrefs() {
117 logger.info("Loading preferences");
118 userprefs = Preferences.userNodeForPackage(MrPostman.class);
119 }
120
121 private void testAndAddModule(String className) {
122 Class c = null;
123
124 try {
125 c = Class.forName(className);
126 Class s = c.getSuperclass();
127 Class webMailSessionClass = WebMailSession.class;
128
129 if (s != webMailSessionClass) {
130 logger.info(className + " Is not a valid module");
131 return;
132 } else {
133 modulesVector.add(c);
134 logger.info("Loaded module: " + className);
135 }
136 } catch (Exception e) {
137 logger.severe("Error opening " + className);
138 return;
139 }
140 }
141
142 private void initModules() {
143 logger.info("initialisation of Modules");
144 modulesVector = new Vector();
145 testAndAddModule("org.mrbook.mrpostman.yahoo.YahooMailSession");
146 testAndAddModule("org.mrbook.mrpostman.hotmail.HotmailMailSession");
147 testAndAddModule("org.mrbook.mrpostman.another.AnotherMailSession");
148 testAndAddModule("org.mrbook.mrpostman.maildotcom.MailDotComMailSession");
149 }
150
151 public String getProperty(String propname, String defaut) {
152 String current = System.getProperty(propname);
153
154 if (current != null) {
155 return current;
156 }
157 return userprefs.get(propname, defaut);
158 }
159
160 public int getPropertyInt(String propname, int i) {
161 return Integer.parseInt(getProperty(propname, Integer.toString(i)));
162 }
163
164 public boolean getPropertyBool(String propname, boolean b) {
165 return getProperty(propname, Boolean.toString(b)).equalsIgnoreCase("true");
166 }
167
168 public static MrPostman getMainInstance() {
169 return maininstance;
170 }
171
172 public void startHelpServer() throws IOException {
173 if (hs == null) {
174 logger.info("Starting HelpServer on port: " + helpPort);
175 hs = new HelpServer(helpPort);
176 Thread t = new Thread(hs);
177 t.start();
178 }
179 }
180
181 /**
182 * Return the base URL for the help system. This will be the root of the doc tree. Requesting this
183 * URL will produce the /index.html document.
184 */
185 public String getHelpBaseUrl() {
186 try {
187 // start the help server...
188 helpPort = getPropertyInt("HelpServerPort", DEFAULT_HELP_PORT);
189 startHelpServer();
190 } catch (IOException e) {
191 logger.warning("A server is already running on the HelpServer port: " + helpPort);
192 }
193 return "http://localhost:" + helpPort + "/";
194 }
195
196 public void showGui() {
197 if (gui == null) {
198 logger.info(" Starting gui");
199 gui = new MrPostmanGui(this);
200 logger.info(" Gui started ");
201 }
202 gui.show();
203 }
204
205 public void exit() {
206 logger.info("Exiting from application");
207 pops.shutdown();
208 System.exit(1);
209 }
210
211 public Vector getModuleNamesVector() {
212 Vector names = new Vector();
213
214 for (Iterator i = modulesVector.iterator(); i.hasNext();) {
215 Class c = (Class) i.next();
216 WebMailSession wms = null;
217
218 try {
219 wms = (WebMailSession) c.newInstance();
220 } catch (Exception e) {
221 logger.log(Level.SEVERE, "should not happen", e);
222 }
223 names.add(wms.getModuleName());
224 }
225 return names;
226 }
227
228 public WebMailSession getModuleHandlerForExtension(String extension) {
229 for (Iterator i = modulesVector.iterator(); i.hasNext();) {
230 Class c = (Class) i.next();
231 WebMailSession wms = null;
232
233 try {
234 wms = (WebMailSession) c.newInstance();
235 } catch (Exception e) {
236 logger.log(Level.SEVERE, "should not happen", e);
237 }
238 String[] extensions = wms.getRecognizedExtensions();
239
240 for (int j = 0; j < extensions.length; j++) {
241 if (extensions[j].compareTo(extension) == 0) {
242 //found correct module
243 initialiseModuleOptions(wms);
244 return wms;
245 }
246 }
247 }
248 return null;
249 }
250
251 /**
252 * Return a list of ModuleInfo objects for all our loaded modules.
253 * This is required for the GUI to initialise the module info panels.
254 * This map is keyed on moduleId.
255 */
256 public HashMap getLoadedModuleInfo() {
257 HashMap moduleInfoList = new HashMap();
258
259 for (Iterator i = modulesVector.iterator(); i.hasNext();) {
260 Class c = (Class) i.next();
261 WebMailSession wms = null;
262
263 try {
264 wms = (WebMailSession) c.newInstance();
265 } catch (Exception e) {
266 logger.log(Level.SEVERE, "should not happen", e);
267 }
268 ModuleInfo mi = wms.getModuleInfo();
269 moduleInfoList.put(mi.getModuleID(), mi);
270 }
271 return moduleInfoList;
272 }
273
274 /**
275 * Set any user defined module specific option values for this module
276 */
277 private void initialiseModuleOptions(WebMailSession module) {
278 //Retrieve the list of module options...
279 ModuleOption[] options = module.getModuleInfo().getOptions();
280
281 //For each attempt to retrieve the last know value for this option from
282 //our prefs, if not know use the default...
283 for (int currOption = 0; currOption < options.length; currOption++) {
284 String name = options[currOption].getName();
285 String value = userprefs.get(name, options[currOption].getDefaultValue());
286
287 //Set this value on our loaded module...
288 module.setOption(name, value);
289 logger.log(Level.FINEST,
290 "Setting option on module " + module.getModuleInfo().getModuleID() + " [" + name + "=" + value + "]");
291 }
292 }
293
294 /**
295 * Return the current value for a module option
296 * This is retrieved from our preferences (if found) or the default value for that option
297 * This is used by the GUI to get current option values for display. This is NOT used by
298 * the WebMailSession objects.
299 */
300 public String getModuleOptionValueForDisplay(String moduleId, String optionId) {
301 //Retrieve the list of module options...
302 ModuleInfo moduleInfo = (ModuleInfo) getLoadedModuleInfo().get(moduleId);
303 ModuleOption[] options = moduleInfo.getOptions();
304
305 //Find the particular option we are interested in (unfortunately we have to do this the long way)...
306 for (int currOption = 0; currOption < options.length; currOption++) {
307 String name = options[currOption].getName();
308
309 if (name.equals(optionId)) {
310 //return the value...
311 return userprefs.get(name, options[currOption].getDefaultValue());
312 }
313 }
314 logger.log(Level.INFO, "Error - couldn't return option value " + optionId);
315 return null; //should never happen!
316 }
317
318 /**
319 * Update our option value in our Prefs for the specified optionId.
320 * Used by MrPostmanGui after the 'Apply' button is pressed.
321 */
322 public void updateModuleOption(String optionId, String value) {
323 logger.log(Level.FINEST, "Update [" + optionId + "] : " + value);
324 userprefs.put(optionId, value);
325 }
326
327 public static void main(String[] args) {
328 logger.info("Beginning starting @APPNAME@ @VERSION@");
329 logger.info("Running with java version: " + System.getProperty("java.version"));
330 logger.info("from: " + System.getProperty("java.vendor"));
331 logger.info("compiled on @DSTAMP@ with @COMPILER@");
332 MrPostman mpn = new MrPostman();
333 logger.info("Finished starting application");
334 }
335 }