View Javadoc
1   /*
2    * DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
3    * Copyright (C) 2009  Mickael Guessant
4    *
5    * This program is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU General Public License
7    * as published by the Free Software Foundation; either version 2
8    * of the License, or (at your option) any later version.
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with this program; if not, write to the Free Software
17   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18   */
19  package davmail;
20  
21  import davmail.caldav.CaldavServer;
22  import davmail.exception.DavMailException;
23  import davmail.exchange.ExchangeSessionFactory;
24  import davmail.http.DavGatewayHttpClientFacade;
25  import davmail.http.DavGatewaySSLProtocolSocketFactory;
26  import davmail.imap.ImapServer;
27  import davmail.ldap.LdapServer;
28  import davmail.pop.PopServer;
29  import davmail.smtp.SmtpServer;
30  import davmail.ui.tray.DavGatewayTray;
31  import org.apache.commons.httpclient.HttpClient;
32  import org.apache.commons.httpclient.HttpStatus;
33  import org.apache.commons.httpclient.methods.GetMethod;
34  import org.apache.log4j.Logger;
35  
36  import java.io.BufferedReader;
37  import java.io.IOException;
38  import java.io.InputStreamReader;
39  import java.util.ArrayList;
40  
41  /**
42   * DavGateway main class
43   */
44  public final class DavGateway {
45      private static final Logger LOGGER = Logger.getLogger(DavGateway.class);
46      private static final String HTTP_DAVMAIL_SOURCEFORGE_NET_VERSION_TXT = "http://davmail.sourceforge.net/version.txt";
47  
48      private static boolean stopped;
49  
50      private DavGateway() {
51      }
52  
53      private static final ArrayList<AbstractServer> SERVER_LIST = new ArrayList<AbstractServer>();
54  
55      /**
56       * Start the gateway, listen on specified smtp and pop3 ports
57       *
58       * @param args command line parameter config file path
59       */
60      public static void main(String[] args) {
61          boolean notray = false;
62          for (String arg:args) {
63              if (arg.startsWith("-")) {
64                  if ("-notray".equals(arg)) {
65                      notray = true;
66                  }
67              } else {
68                  Settings.setConfigFilePath(arg);
69              }
70          }
71  
72          Settings.load();
73          DavGatewayTray.init(notray);
74  
75          start();
76  
77          // server mode: all threads are daemon threads, do not let main stop
78          if (Settings.getBooleanProperty("davmail.server")) {
79              Runtime.getRuntime().addShutdownHook(new Thread("Shutdown") {
80                  @Override
81                  public void run() {
82                      DavGatewayTray.debug(new BundleMessage("LOG_GATEWAY_INTERRUPTED"));
83                      DavGateway.stop();
84                      stopped = true;
85                  }
86              });
87  
88              try {
89                  while (!stopped) {
90                      Thread.sleep(1000);
91                  }
92              } catch (InterruptedException e) {
93                  DavGatewayTray.debug(new BundleMessage("LOG_GATEWAY_INTERRUPTED"));
94                  stop();
95                  DavGatewayTray.debug(new BundleMessage("LOG_GATEWAY_STOP"));
96              }
97  
98          }
99      }
100 
101     /**
102      * Start DavMail listeners.
103      */
104     public static void start() {
105         // register custom SSL Socket factory
106         DavGatewaySSLProtocolSocketFactory.register();
107 
108         // prepare HTTP connection pool
109         DavGatewayHttpClientFacade.start();
110 
111         SERVER_LIST.clear();
112 
113         int smtpPort = Settings.getIntProperty("davmail.smtpPort");
114         if (smtpPort != 0) {
115             SERVER_LIST.add(new SmtpServer(smtpPort));
116         }
117         int popPort = Settings.getIntProperty("davmail.popPort");
118         if (popPort != 0) {
119             SERVER_LIST.add(new PopServer(popPort));
120         }
121         int imapPort = Settings.getIntProperty("davmail.imapPort");
122         if (imapPort != 0) {
123             SERVER_LIST.add(new ImapServer(imapPort));
124         }
125         int caldavPort = Settings.getIntProperty("davmail.caldavPort");
126         if (caldavPort != 0) {
127             SERVER_LIST.add(new CaldavServer(caldavPort));
128         }
129         int ldapPort = Settings.getIntProperty("davmail.ldapPort");
130         if (ldapPort != 0) {
131             SERVER_LIST.add(new LdapServer(ldapPort));
132         }
133 
134         BundleMessage.BundleMessageList messages = new BundleMessage.BundleMessageList();
135         BundleMessage.BundleMessageList errorMessages = new BundleMessage.BundleMessageList();
136         for (AbstractServer server : SERVER_LIST) {
137             try {
138                 server.bind();
139                 server.start();
140                 messages.add(new BundleMessage("LOG_PROTOCOL_PORT", server.getProtocolName(), server.getPort()));
141             } catch (DavMailException e) {
142                 errorMessages.add(e.getBundleMessage());
143             }
144         }
145 
146         final String currentVersion = getCurrentVersion();
147         boolean showStartupBanner = Settings.getBooleanProperty("davmail.showStartupBanner", true);
148         if (showStartupBanner) {
149             DavGatewayTray.info(new BundleMessage("LOG_DAVMAIL_GATEWAY_LISTENING",
150                     currentVersion == null ? "" : currentVersion, messages));
151         }
152         if (!errorMessages.isEmpty()) {
153             DavGatewayTray.error(new BundleMessage("LOG_MESSAGE", errorMessages));
154         }
155 
156         // check for new version in a separate thread
157         new Thread("CheckRelease") {
158             @Override
159             public void run() {
160                 String releasedVersion = getReleasedVersion();
161                 if (currentVersion != null && currentVersion.length() > 0 && releasedVersion != null && currentVersion.compareTo(releasedVersion) < 0) {
162                     DavGatewayTray.info(new BundleMessage("LOG_NEW_VERSION_AVAILABLE", releasedVersion));
163                 }
164 
165             }
166         }.start();
167 
168     }
169 
170     /**
171      * Stop all listeners, shutdown connection pool and clear session cache.
172      */
173     public static void stop() {
174         DavGateway.stopServers();
175         // close pooled connections
176         DavGatewayHttpClientFacade.stop();
177         // clear session cache
178         ExchangeSessionFactory.reset();
179         DavGatewayTray.info(new BundleMessage("LOG_GATEWAY_STOP"));
180         DavGatewayTray.dispose();
181     }
182 
183     /**
184      * Stop all listeners and clear session cache.
185      */
186     public static void restart() {
187         DavGateway.stopServers();
188         // clear session cache
189         ExchangeSessionFactory.reset();
190         DavGateway.start();
191     }
192 
193     private static void stopServers() {
194         for (AbstractServer server : SERVER_LIST) {
195             server.close();
196             try {
197                 server.join();
198             } catch (InterruptedException e) {
199                 DavGatewayTray.warn(new BundleMessage("LOG_EXCEPTION_WAITING_SERVER_THREAD_DIE"), e);
200             }
201         }
202     }
203 
204     /**
205      * Get current DavMail version.
206      *
207      * @return current version
208      */
209     public static String getCurrentVersion() {
210         Package davmailPackage = DavGateway.class.getPackage();
211         String currentVersion = davmailPackage.getImplementationVersion();
212         if (currentVersion == null) {
213             currentVersion = "";
214         }
215         return currentVersion;
216     }
217 
218     /**
219      * Get latest released version from SourceForge.
220      *
221      * @return latest version
222      */
223     public static String getReleasedVersion() {
224         String version = null;
225         if (!Settings.getBooleanProperty("davmail.disableUpdateCheck")) {
226             BufferedReader versionReader = null;
227             GetMethod getMethod = new GetMethod(HTTP_DAVMAIL_SOURCEFORGE_NET_VERSION_TXT);
228             try {
229                 HttpClient httpClient = DavGatewayHttpClientFacade.getInstance(HTTP_DAVMAIL_SOURCEFORGE_NET_VERSION_TXT);
230                 int status = httpClient.executeMethod(getMethod);
231                 if (status == HttpStatus.SC_OK) {
232                     versionReader = new BufferedReader(new InputStreamReader(getMethod.getResponseBodyAsStream(), "UTF-8"));
233                     version = versionReader.readLine();
234                     LOGGER.debug("DavMail released version: " + version);
235                 }
236             } catch (IOException e) {
237                 DavGatewayTray.debug(new BundleMessage("LOG_UNABLE_TO_GET_RELEASED_VERSION"));
238             } finally {
239                 if (versionReader != null) {
240                     try {
241                         versionReader.close();
242                     } catch (IOException e) {
243                         // ignore
244                     }
245                 }
246                 getMethod.releaseConnection();
247             }
248         }
249         return version;
250     }
251 }