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.exchange.auth.ExchangeAuthenticator;
25  import davmail.http.HttpClientAdapter;
26  import davmail.http.request.GetRequest;
27  import davmail.imap.ImapServer;
28  import davmail.ldap.LdapServer;
29  import davmail.pop.PopServer;
30  import davmail.smtp.SmtpServer;
31  import davmail.ui.tray.DavGatewayTray;
32  import org.apache.log4j.Logger;
33  
34  import java.awt.*;
35  import java.io.IOException;
36  import java.lang.reflect.InvocationTargetException;
37  import java.util.ArrayList;
38  
39  /**
40   * DavGateway main class
41   */
42  public final class DavGateway {
43      private static final Logger LOGGER = Logger.getLogger(DavGateway.class);
44      private static final String HTTP_DAVMAIL_SOURCEFORGE_NET_VERSION_TXT = "https://davmail.sourceforge.net/version.txt";
45  
46      private static final Object LOCK = new Object();
47      private static boolean shutdown = false;
48  
49      private DavGateway() {
50      }
51  
52      private static final ArrayList<AbstractServer> SERVER_LIST = new ArrayList<>();
53  
54      /**
55       * Start the gateway, listen on specified smtp and pop3 ports
56       *
57       * @param args command line parameter config file path
58       */
59      public static void main(String[] args) {
60          boolean notray = false;
61          boolean server = false;
62          boolean token = false;
63          for (String arg : args) {
64              if (arg.startsWith("-")) {
65                  if ("-notray".equals(arg)) {
66                      notray = true;
67                  } else if ("-server".equals(arg)) {
68                      server = true;
69                  } else if ("-token".equals(arg)) {
70                      token = true;
71                  }
72              } else {
73                  Settings.setConfigFilePath(arg);
74              }
75          }
76  
77          Settings.load();
78          if (token) {
79              try {
80                  ExchangeAuthenticator authenticator = (ExchangeAuthenticator) Class.forName("davmail.exchange.auth.O365InteractiveAuthenticator")
81                          .getDeclaredConstructor().newInstance();
82                  authenticator.setUsername("");
83                  authenticator.authenticate();
84                  System.out.println(authenticator.getToken().getRefreshToken());
85              } catch (IOException | ClassNotFoundException | NoSuchMethodException | InstantiationException |
86                       IllegalAccessException | InvocationTargetException e) {
87                  System.err.println(e+" "+e.getMessage());
88              }
89  
90          } else {
91  
92              if (GraphicsEnvironment.isHeadless()) {
93                  // force server mode
94                  LOGGER.debug("Headless mode, do not create GUI");
95                  server = true;
96              }
97              if (server) {
98                  Settings.setProperty("davmail.server", "true");
99                  Settings.updateLoggingConfig();
100             }
101 
102 
103             if (Settings.getBooleanProperty("davmail.server")) {
104                 LOGGER.debug("Start DavMail in server mode");
105             } else {
106                 LOGGER.debug("Start DavMail in GUI mode");
107                 DavGatewayTray.init(notray);
108             }
109 
110             start();
111 
112             // server mode: all threads are daemon threads, do not let main stop
113             if (Settings.getBooleanProperty("davmail.server")) {
114                 Runtime.getRuntime().addShutdownHook(new Thread("Shutdown") {
115                     @Override
116                     public void run() {
117                         shutdown = true;
118                         DavGatewayTray.debug(new BundleMessage("LOG_GATEWAY_INTERRUPTED"));
119                         DavGateway.stop();
120                         synchronized (LOCK) {
121                             LOCK.notifyAll();
122                         }
123                     }
124                 });
125 
126                 synchronized (LOCK) {
127                     try {
128                         while (!shutdown) {
129                             LOCK.wait();
130                         }
131                     } catch (InterruptedException e) {
132                         DavGatewayTray.debug(new BundleMessage("LOG_GATEWAY_INTERRUPTED"));
133                         Thread.currentThread().interrupt();
134                     }
135                 }
136 
137             }
138         }
139     }
140 
141     /**
142      * Start DavMail listeners.
143      */
144     public static void start() {
145         SERVER_LIST.clear();
146 
147         int smtpPort = Settings.getIntProperty("davmail.smtpPort");
148         if (smtpPort != 0) {
149             SERVER_LIST.add(new SmtpServer(smtpPort));
150         }
151         int popPort = Settings.getIntProperty("davmail.popPort");
152         if (popPort != 0) {
153             SERVER_LIST.add(new PopServer(popPort));
154         }
155         int imapPort = Settings.getIntProperty("davmail.imapPort");
156         if (imapPort != 0) {
157             SERVER_LIST.add(new ImapServer(imapPort));
158         }
159         int caldavPort = Settings.getIntProperty("davmail.caldavPort");
160         if (caldavPort != 0) {
161             SERVER_LIST.add(new CaldavServer(caldavPort));
162         }
163         int ldapPort = Settings.getIntProperty("davmail.ldapPort");
164         if (ldapPort != 0) {
165             SERVER_LIST.add(new LdapServer(ldapPort));
166         }
167 
168         BundleMessage.BundleMessageList messages = new BundleMessage.BundleMessageList();
169         BundleMessage.BundleMessageList errorMessages = new BundleMessage.BundleMessageList();
170         for (AbstractServer server : SERVER_LIST) {
171             try {
172                 server.bind();
173                 server.start();
174                 messages.add(new BundleMessage("LOG_PROTOCOL_PORT", server.getProtocolName(), server.getPort()));
175             } catch (DavMailException e) {
176                 errorMessages.add(e.getBundleMessage());
177             }
178         }
179 
180         final String currentVersion = getCurrentVersion();
181         boolean showStartupBanner = Settings.getBooleanProperty("davmail.showStartupBanner", true);
182         if (showStartupBanner) {
183             DavGatewayTray.info(new BundleMessage("LOG_DAVMAIL_GATEWAY_LISTENING", currentVersion, messages));
184         }
185         if (!errorMessages.isEmpty()) {
186             DavGatewayTray.error(new BundleMessage("LOG_MESSAGE", errorMessages));
187         }
188 
189         // check for new version in a separate thread
190         new Thread("CheckRelease") {
191             @Override
192             public void run() {
193                 String releasedVersion = getReleasedVersion();
194                 if (!currentVersion.isEmpty() && releasedVersion != null && currentVersion.compareTo(releasedVersion) < 0) {
195                     DavGatewayTray.info(new BundleMessage("LOG_NEW_VERSION_AVAILABLE", releasedVersion));
196                 }
197 
198             }
199         }.start();
200 
201     }
202 
203     /**
204      * Stop all listeners, shutdown connection pool and clear session cache.
205      */
206     public static void stop() {
207         DavGateway.stopServers();
208         // close pooled connections
209         ExchangeSessionFactory.shutdown();
210         DavGatewayTray.info(new BundleMessage("LOG_GATEWAY_STOP"));
211         DavGatewayTray.dispose();
212     }
213 
214     /**
215      * Stop all listeners and clear session cache.
216      */
217     public static void restart() {
218         DavGateway.stopServers();
219         // clear session cache
220         ExchangeSessionFactory.shutdown();
221         DavGateway.start();
222     }
223 
224     private static void stopServers() {
225         for (AbstractServer server : SERVER_LIST) {
226             server.close();
227             try {
228                 server.join();
229             } catch (InterruptedException e) {
230                 DavGatewayTray.warn(new BundleMessage("LOG_EXCEPTION_WAITING_SERVER_THREAD_DIE"), e);
231                 Thread.currentThread().interrupt();
232             }
233         }
234     }
235 
236     /**
237      * Get current DavMail version.
238      *
239      * @return current version
240      */
241     public static String getCurrentVersion() {
242         Package davmailPackage = DavGateway.class.getPackage();
243         String currentVersion = davmailPackage.getImplementationVersion();
244         if (currentVersion == null) {
245             currentVersion = "";
246         }
247         return currentVersion;
248     }
249 
250     /**
251      * Get latest released version from SourceForge.
252      *
253      * @return latest version
254      */
255     public static String getReleasedVersion() {
256         String version = null;
257         if (!Settings.getBooleanProperty("davmail.disableUpdateCheck")) {
258             try (HttpClientAdapter httpClientAdapter = new HttpClientAdapter(HTTP_DAVMAIL_SOURCEFORGE_NET_VERSION_TXT)) {
259                 GetRequest getRequest = new GetRequest(HTTP_DAVMAIL_SOURCEFORGE_NET_VERSION_TXT);
260                 getRequest = httpClientAdapter.executeFollowRedirect(getRequest);
261                 version = getRequest.getResponseBodyAsString();
262                 LOGGER.debug("DavMail released version: " + version);
263             } catch (IOException e) {
264                 DavGatewayTray.debug(new BundleMessage("LOG_UNABLE_TO_GET_RELEASED_VERSION"));
265             }
266         }
267         return version;
268     }
269 }