git clone of logicmail with some fixes/features added
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Added experimental WiFi connection handover support (refs #79)

git-svn-id: https://logicmail.svn.sourceforge.net/svnroot/logicmail/trunk@964 5c734088-3d25-0410-9155-b3c3832efda5

octorian 7e28665b b12dac86

+485 -28
+1
LogicMail/res/org/logicprobe/LogicMail/LogicMail.rrc
··· 73 73 CONFIG_ACCOUNT_USERNAME#0="Username:"; 74 74 CONFIG_GLOBAL_AUTO_STARTUP#0="Auto startup"; 75 75 CONFIG_GLOBAL_CONNECTION_DEBUGGING#0="Connection debugging"; 76 + CONFIG_GLOBAL_ENABLE_HANDOVER#0="Switch to WiFi on coverage changes"; 76 77 CONFIG_GLOBAL_ENABLE_WIFI#0="Use WiFi if available"; 77 78 CONFIG_GLOBAL_EXPUNGE_ALWAYS#0="Always"; 78 79 CONFIG_GLOBAL_EXPUNGE_BEHAVIOR#0="Remove deleted messages?";
+1
LogicMail/res/org/logicprobe/LogicMail/LogicMail.rrh
··· 287 287 CONFIG_IDENTITY_DEFAULT_NAME#0=291; 288 288 MENUITEM_GET_HTML#0=292; 289 289 MENUITEM_GET_PLAIN_TEXT#0=294; 290 + CONFIG_GLOBAL_ENABLE_HANDOVER#0=295;
+30 -1
LogicMail/src/org/logicprobe/LogicMail/conf/GlobalConfig.java
··· 83 83 private int transportType; 84 84 /** Whether WiFi should be used if available */ 85 85 private boolean enableWiFi; 86 + /** Whether mobile-to-WiFi connection handover should be attempted. */ 87 + private boolean connectionHandoverEnabled; 86 88 /** Connection debugging */ 87 89 private boolean connDebug; 88 90 /** Hide deleted messages */ ··· 134 136 this.dispOrder = false; 135 137 this.transportType = ConnectionConfig.TRANSPORT_AUTO; 136 138 this.enableWiFi = true; 139 + this.connectionHandoverEnabled = false; 137 140 this.hideDeletedMsg = true; 138 141 this.localHostname = ""; 139 142 this.filesystemRoot = ""; ··· 316 319 changeType |= CHANGE_TYPE_NETWORK; 317 320 } 318 321 } 319 - 322 + 323 + /** 324 + * Checks if mobile-to-WiFi connection handover is enabled. 325 + * 326 + * @return true, if connection handover is enabled 327 + */ 328 + public boolean isConnectionHandoverEnabled() { 329 + return connectionHandoverEnabled; 330 + } 331 + 332 + /** 333 + * Sets whether mobile-to-WiFi connection handover is enabled. 334 + * 335 + * @param connectionHandoverEnabled True to enable, false to disable 336 + */ 337 + public void setConnectionHandoverEnabled(boolean connectionHandoverEnabled) { 338 + if(this.connectionHandoverEnabled != connectionHandoverEnabled) { 339 + this.connectionHandoverEnabled = connectionHandoverEnabled; 340 + changeType |= CHANGE_TYPE_NETWORK; 341 + } 342 + } 343 + 320 344 /** 321 345 * Gets the connection debugging mode. 322 346 * ··· 479 503 table.put("global_filesystemRoot", filesystemRoot); 480 504 table.put("global_transportType", new Integer(transportType)); 481 505 table.put("global_enableWiFi", new Boolean(enableWiFi)); 506 + table.put("global_connectionHandoverEnabled", new Boolean(connectionHandoverEnabled)); 482 507 table.put("global_connDebug", new Boolean(connDebug)); 483 508 table.put("global_hideDeletedMsg", new Boolean(hideDeletedMsg)); 484 509 table.put("global_localHostname", localHostname); ··· 530 555 value = table.get("global_enableWiFi"); 531 556 if(value instanceof Boolean) { 532 557 enableWiFi = ((Boolean)value).booleanValue(); 558 + } 559 + value = table.get("global_connectionHandoverEnabled"); 560 + if(value instanceof Boolean) { 561 + connectionHandoverEnabled = ((Boolean)value).booleanValue(); 533 562 } 534 563 value = table.get("global_connDebug"); 535 564 if (value instanceof Boolean) {
+16 -1
LogicMail/src/org/logicprobe/LogicMail/mail/AbstractMailConnectionHandler.java
··· 155 155 } 156 156 } 157 157 158 + /** 159 + * Pushes a request onto the head of the queue. 160 + * If the connection is shutting down, all requests will be ignored. 161 + * 162 + * @param request Request object to be pushed 163 + */ 164 + public void pushRequest(ConnectionHandlerRequest request) { 165 + synchronized(requestQueue) { 166 + if(!shutdownInProgress) { 167 + requestQueue.push(request); 168 + requestQueue.notifyAll(); 169 + } 170 + } 171 + } 172 + 158 173 /** 159 174 * Handles the CLOSED state. 160 175 */ ··· 224 239 * @throws IOException on I/O errors 225 240 * @throws MailException on protocol errors 226 241 */ 227 - private void handleOpenedConnection() throws IOException, MailException { 242 + protected void handleOpenedConnection() throws IOException, MailException { 228 243 showTransitionStatus(null); 229 244 retryCount = 0; 230 245 synchronized(requestQueue) {
+16
LogicMail/src/org/logicprobe/LogicMail/mail/IncomingMailClient.java
··· 40 40 import org.logicprobe.LogicMail.message.MessageFlags; 41 41 import org.logicprobe.LogicMail.message.MimeMessageContent; 42 42 import org.logicprobe.LogicMail.message.MimeMessagePart; 43 + import org.logicprobe.LogicMail.util.Connection; 43 44 44 45 /** 45 46 * Provides a generic interface to different incoming mail protocols. ··· 57 58 * </p> 58 59 */ 59 60 public interface IncomingMailClient extends MailClient { 61 + /** 62 + * Open a new session with the mail server, on an already open connection. 63 + * This method assumes that it is being provided a newly created socket 64 + * connection, which it will then send protocol-specific login commands to. 65 + * It should also be possible to invoke this method multiple times 66 + * to correct for authentication failures, without having to reopen 67 + * the underlying connection. 68 + * 69 + * @param connection Newly opened socket connection 70 + * @return True if successful, false on authentication failure 71 + * @throws IOException on I/O errors 72 + * @throws MailException on protocol errors 73 + */ 74 + boolean open(Connection connection) throws IOException, MailException; 75 + 60 76 /** 61 77 * Set the listener used to handle asynchronous events from the mail client. 62 78 *
+88 -3
LogicMail/src/org/logicprobe/LogicMail/mail/IncomingMailConnectionHandler.java
··· 37 37 38 38 import net.rim.device.api.system.Backlight; 39 39 import net.rim.device.api.system.DeviceInfo; 40 + import net.rim.device.api.system.WLANInfo; 40 41 import net.rim.device.api.ui.UiApplication; 41 42 42 43 import org.logicprobe.LogicMail.conf.AccountConfig; 44 + import org.logicprobe.LogicMail.conf.ConnectionConfig; 45 + import org.logicprobe.LogicMail.conf.MailSettings; 43 46 import org.logicprobe.LogicMail.message.MessageFlags; 44 47 import org.logicprobe.LogicMail.util.Queue; 45 48 ··· 87 90 88 91 private static final int MS_PER_MIN = 60000; 89 92 private static final int REFRESH_TOLERANCE = 60000; 93 + 94 + private String lastWiFiAttemptSSID; 95 + private long lastWiFiAttemptTime; 96 + private int wifiAttemptCount; 90 97 91 98 /** 92 99 * Listener to handle asynchronous notifications from the mail client. ··· 290 297 // An idle timeout on a mail store with locked folders should 291 298 // be handled by promptly disconnecting. That way, any further 292 299 // data requests will cause a reconnect and get fresh data. 293 - NetworkDisconnectRequest disconnectRequest = new NetworkDisconnectRequest(mailStore, NetworkDisconnectRequest.REQUEST_DISCONNECT_TIMEOUT); 300 + NetworkDisconnectRequest disconnectRequest = 301 + new NetworkDisconnectRequest(mailStore, NetworkDisconnectRequest.REQUEST_DISCONNECT_TIMEOUT); 294 302 disconnectRequest.setDeliberate(false); 295 303 mailStore.processRequest(disconnectRequest); 296 304 } ··· 314 322 handleSetActiveFolder(inboxFolder); 315 323 } 316 324 } 325 + 326 + // Handover is attempted during idle timeout processing, 327 + // only if a refresh is about to be triggered. 317 328 handleConnectionIdleTimeout(System.currentTimeMillis() - idleStartTime); 318 329 } 319 330 } 331 + else { 332 + attemptConnectionHandover(); 333 + } 334 + } 335 + 336 + private void attemptConnectionHandover() { 337 + if(tryBetterConnection()) { 338 + NetworkHandoverRequest handoverRequest = new NetworkHandoverRequest(mailStore); 339 + handoverRequest.setDeliberate(false); 340 + handoverRequest.setRequestCallback(new MailStoreRequestCallback() { 341 + public void mailStoreRequestComplete(MailStoreRequest request) { 342 + NetworkHandoverRequest handoverRequest = (NetworkHandoverRequest)request; 343 + lastWiFiAttemptSSID = handoverRequest.getAttemptedSSID(); 344 + lastWiFiAttemptTime = handoverRequest.getAttemptTime(); 345 + wifiAttemptCount = 0; 346 + } 347 + public void mailStoreRequestFailed(MailStoreRequest request, Throwable exception, boolean isFinal) { 348 + NetworkHandoverRequest handoverRequest = (NetworkHandoverRequest)request; 349 + lastWiFiAttemptSSID = handoverRequest.getAttemptedSSID(); 350 + lastWiFiAttemptTime = handoverRequest.getAttemptTime(); 351 + wifiAttemptCount++; 352 + } 353 + }); 354 + mailStore.processRequestFirst(handoverRequest); 355 + } 320 356 } 321 357 358 + private boolean tryBetterConnection() { 359 + if(!MailSettings.getInstance().getGlobalConfig().isConnectionHandoverEnabled()) { 360 + return false; 361 + } 362 + 363 + // Check if we are not currently connected via WiFi, but WiFi is 364 + // available and enabled in the configuration. 365 + if(incomingClient.getConnectionType() != ConnectionConfig.TRANSPORT_WIFI_ONLY 366 + && WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED 367 + && isWiFiConfigured()) { 368 + // If we've previously tried connecting via WiFi 369 + if(lastWiFiAttemptSSID != null && lastWiFiAttemptTime != 0) { 370 + // If the WiFi SSID has changed 371 + WLANInfo.WLANAPInfo apInfo = WLANInfo.getAPInfo(); 372 + if(apInfo != null && !lastWiFiAttemptSSID.equals(apInfo.getSSID())) { 373 + wifiAttemptCount = 0; 374 + return true; 375 + } 376 + // If its been more than two minutes since our last attempt, and 377 + // we haven't failed too many times 378 + else if((System.currentTimeMillis() - lastWiFiAttemptTime) > 120000 379 + && wifiAttemptCount < 2) { 380 + return true; 381 + } 382 + else { 383 + return false; 384 + } 385 + } 386 + else { 387 + return true; 388 + } 389 + } 390 + else { 391 + return false; 392 + } 393 + } 394 + 395 + private boolean isWiFiConfigured() { 396 + if(accountConfig.getTransportType() == ConnectionConfig.TRANSPORT_GLOBAL) { 397 + return MailSettings.getInstance().getGlobalConfig().getEnableWiFi(); 398 + } 399 + else { 400 + return accountConfig.getEnableWiFi(); 401 + } 402 + } 403 + 322 404 void handleRequestDisconnect() throws IOException, MailException { 323 405 this.previousActiveFolder = null; 324 - throw new MailException("", true, REQUEST_DISCONNECT); 406 + throw new MailException("Requested disconnect", true, REQUEST_DISCONNECT); 325 407 } 326 408 327 409 void handleRequestDisconnectTimeout() throws IOException, MailException { 328 410 this.previousActiveFolder = null; 329 411 handleConnectionDisconnectTimeout(System.currentTimeMillis() - idleStartTime); 330 - throw new MailException("", true, REQUEST_DISCONNECT_TIMEOUT); 412 + throw new MailException("Timeout disconnect", true, REQUEST_DISCONNECT_TIMEOUT); 331 413 } 332 414 333 415 private void handleSetActiveFolder(FolderTreeItem folder) throws IOException, MailException { ··· 356 438 // then we should trigger a refresh. 357 439 if(Math.abs(accumulatedIdleTime - refreshFrequency) < REFRESH_TOLERANCE) { 358 440 accumulatedIdleTime = 0; 441 + 442 + attemptConnectionHandover(); 443 + 359 444 mailStore.fireRefreshRequired(false); 360 445 } 361 446 }
+17 -9
LogicMail/src/org/logicprobe/LogicMail/mail/MailClient.java
··· 53 53 * @throws IOException on I/O errors 54 54 * @throws MailException on protocol errors 55 55 */ 56 - public abstract boolean open() throws IOException, MailException; 56 + boolean open() throws IOException, MailException; 57 57 58 58 /** 59 59 * Close an existing connection. ··· 63 63 * @throws IOException on I/O errors 64 64 * @throws MailException on protocol errors 65 65 */ 66 - public abstract void close() throws IOException, MailException; 66 + void close() throws IOException, MailException; 67 67 68 68 /** 69 69 * Gets the connection configuration associated with this client. 70 70 * @return Connection configuration. 71 71 */ 72 - public abstract ConnectionConfig getConnectionConfig(); 72 + ConnectionConfig getConnectionConfig(); 73 73 74 74 /** 75 75 * Find out if the connection is active. 76 76 * @return True if the connection is active, false otherwise 77 77 */ 78 - public abstract boolean isConnected(); 78 + boolean isConnected(); 79 79 80 80 /** 81 + * Gets the type of connection that was opened. 82 + * 83 + * @return the connection type, based on the 84 + * <code>ConnectionConfig.TRANSPORT_XXXX</code> constants. 85 + */ 86 + int getConnectionType(); 87 + 88 + /** 81 89 * Checks if a valid username and password are required for this client. 82 90 * @return true, if login is required 83 91 */ 84 - public abstract boolean isLoginRequired(); 92 + boolean isLoginRequired(); 85 93 86 94 /** 87 95 * Get the configured username for this client. 88 96 * @return Configured username, empty if none, null if n/a 89 97 */ 90 - public abstract String getUsername(); 98 + String getUsername(); 91 99 92 100 /** 93 101 * Set the username for this client to use 94 102 * @param username The username 95 103 */ 96 - public abstract void setUsername(String username); 104 + void setUsername(String username); 97 105 98 106 /** 99 107 * Get the configured password for this client. 100 108 * @return Configured password, empty if none, null if n/a 101 109 */ 102 - public abstract String getPassword(); 110 + String getPassword(); 103 111 104 112 /** 105 113 * Set the password for this client to use 106 114 * @param password The password 107 115 */ 108 - public abstract void setPassword(String password); 116 + void setPassword(String password); 109 117 }
+106
LogicMail/src/org/logicprobe/LogicMail/mail/NetworkHandoverRequest.java
··· 1 + /*- 2 + * Copyright (c) 2011, Derek Konigsberg 3 + * All rights reserved. 4 + * 5 + * Redistribution and use in source and binary forms, with or without 6 + * modification, are permitted provided that the following conditions 7 + * are met: 8 + * 9 + * 1. Redistributions of source code must retain the above copyright 10 + * notice, this list of conditions and the following disclaimer. 11 + * 2. Redistributions in binary form must reproduce the above copyright 12 + * notice, this list of conditions and the following disclaimer in the 13 + * documentation and/or other materials provided with the distribution. 14 + * 3. Neither the name of the project nor the names of its 15 + * contributors may be used to endorse or promote products derived 16 + * from this software without specific prior written permission. 17 + * 18 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 29 + * OF THE POSSIBILITY OF SUCH DAMAGE. 30 + */ 31 + package org.logicprobe.LogicMail.mail; 32 + 33 + import java.io.IOException; 34 + 35 + import org.logicprobe.LogicMail.conf.ConnectionConfig; 36 + import org.logicprobe.LogicMail.conf.MailSettings; 37 + import org.logicprobe.LogicMail.util.Connection; 38 + import org.logicprobe.LogicMail.util.NetworkConnector; 39 + import org.logicprobe.LogicMail.util.UtilFactory; 40 + 41 + import net.rim.device.api.system.WLANInfo; 42 + 43 + class NetworkHandoverRequest extends NetworkMailStoreRequest implements MailStoreRequest { 44 + private String attemptedSSID; 45 + private long attemptTime; 46 + 47 + NetworkHandoverRequest(NetworkMailStore mailStore) { 48 + super(mailStore); 49 + } 50 + 51 + protected String getInitialStatus() { 52 + return null; 53 + } 54 + 55 + public String getAttemptedSSID() { 56 + return attemptedSSID; 57 + } 58 + 59 + public long getAttemptTime() { 60 + return attemptTime; 61 + } 62 + 63 + public void execute(MailClient client) throws IOException, MailException { 64 + IncomingMailClient incomingClient = (IncomingMailClient)client; 65 + if(!prepareForHandover(incomingClient)) { 66 + fireMailStoreRequestFailed(null, true); 67 + return; 68 + } 69 + 70 + Connection connection; 71 + try { 72 + NetworkConnector connector = UtilFactory.getInstance().getNetworkConnector( 73 + MailSettings.getInstance().getGlobalConfig(), 74 + incomingClient.getAcctConfig()); 75 + connection = connector.open(incomingClient.getAcctConfig(), true); 76 + if(connection.getConnectionType() != ConnectionConfig.TRANSPORT_WIFI_ONLY) { 77 + connection.close(); 78 + connection = null; 79 + } 80 + } catch (IOException e) { 81 + fireMailStoreRequestFailed(e, true); 82 + return; 83 + } 84 + 85 + if(connection == null) { 86 + fireMailStoreRequestFailed(null, true); 87 + } 88 + 89 + incomingClient.close(); 90 + incomingClient.open(connection); 91 + fireMailStoreRequestComplete(); 92 + } 93 + 94 + private boolean prepareForHandover(IncomingMailClient incomingClient) { 95 + if(incomingClient.getConnectionType() != ConnectionConfig.TRANSPORT_WIFI_ONLY 96 + && WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED) { 97 + WLANInfo.WLANAPInfo apInfo = WLANInfo.getAPInfo(); 98 + if(apInfo != null) { 99 + attemptedSSID = apInfo.getSSID(); 100 + attemptTime = System.currentTimeMillis(); 101 + return true; 102 + } 103 + } 104 + return false; 105 + } 106 + }
+16
LogicMail/src/org/logicprobe/LogicMail/mail/NetworkMailStore.java
··· 319 319 } 320 320 } 321 321 322 + /** 323 + * Submits the request to the mail store for processing, placing it at the 324 + * top of the request queue. 325 + * 326 + * @param request the request to process 327 + */ 328 + public void processRequestFirst(MailStoreRequest request) { 329 + if(request instanceof NetworkMailStoreRequest 330 + && request instanceof ConnectionHandlerRequest) { 331 + connectionHandler.pushRequest((ConnectionHandlerRequest)request); 332 + } 333 + else { 334 + throw new IllegalArgumentException(); 335 + } 336 + } 337 + 322 338 IncomingMailConnectionHandler getConnectionHandler() { 323 339 return connectionHandler; 324 340 }
+25 -2
LogicMail/src/org/logicprobe/LogicMail/mail/imap/ImapClient.java
··· 186 186 password = accountConfig.getServerPass(); 187 187 } 188 188 } 189 - 189 + 190 190 /* (non-Javadoc) 191 191 * @see org.logicprobe.LogicMail.mail.MailClient#open() 192 192 */ 193 193 public boolean open() throws IOException, MailException { 194 + if(!openStarted) { 195 + Connection localConnection = networkConnector.open(accountConfig); 196 + return open(localConnection); 197 + } 198 + else { 199 + return open(connection); 200 + } 201 + } 202 + 203 + /* (non-Javadoc) 204 + * @see org.logicprobe.LogicMail.mail.IncomingMailClient#open(org.logicprobe.LogicMail.util.Connection) 205 + */ 206 + public boolean open(Connection localConnection) throws IOException, MailException { 207 + if(openStarted && connection != localConnection) { 208 + close(); 209 + } 194 210 try { 195 211 if(!openStarted) { 196 212 watchdog.shutdown(); 197 - connection = networkConnector.open(accountConfig); 213 + this.connection = localConnection; 198 214 imapProtocol.setConnection(connection); 199 215 imapProtocol.setWatchdog(watchdog); 200 216 watchdog.setDefaultTimeoutForConnection(connection.getConnectionType()); ··· 296 312 */ 297 313 public boolean isConnected() { 298 314 return connection != null && connection.isConnected(); 315 + } 316 + 317 + /* (non-Javadoc) 318 + * @see org.logicprobe.LogicMail.mail.MailClient#getConnectionType() 319 + */ 320 + public int getConnectionType() { 321 + return (connection != null) ? connection.getConnectionType() : -1; 299 322 } 300 323 301 324 /* (non-Javadoc)
+24 -1
LogicMail/src/org/logicprobe/LogicMail/mail/pop/PopClient.java
··· 166 166 */ 167 167 public boolean open() throws IOException, MailException { 168 168 if(!openStarted) { 169 + Connection localConnection = networkConnector.open(accountConfig); 170 + return open(localConnection); 171 + } 172 + else { 173 + return open(connection); 174 + } 175 + } 176 + 177 + /* (non-Javadoc) 178 + * @see org.logicprobe.LogicMail.mail.IncomingMailClient#open(org.logicprobe.LogicMail.util.Connection) 179 + */ 180 + public boolean open(Connection localConnection) throws IOException, MailException { 181 + if(openStarted && connection != localConnection) { 182 + close(); 183 + } 184 + if(!openStarted) { 169 185 watchdog.shutdown(); 170 - connection = networkConnector.open(accountConfig); 186 + this.connection = localConnection; 171 187 popProtocol.setConnection(connection); 172 188 popProtocol.setWatchdog(watchdog); 173 189 watchdog.setDefaultTimeoutForConnection(connection.getConnectionType()); ··· 247 263 */ 248 264 public boolean isConnected() { 249 265 return connection != null && connection.isConnected(); 266 + } 267 + 268 + /* (non-Javadoc) 269 + * @see org.logicprobe.LogicMail.mail.MailClient#getConnectionType() 270 + */ 271 + public int getConnectionType() { 272 + return (connection != null) ? connection.getConnectionType() : -1; 250 273 } 251 274 252 275 /* (non-Javadoc)
+4
LogicMail/src/org/logicprobe/LogicMail/mail/smtp/SmtpClient.java
··· 203 203 return connection != null && connection.isConnected(); 204 204 } 205 205 206 + public int getConnectionType() { 207 + return (connection != null) ? connection.getConnectionType() : -1; 208 + } 209 + 206 210 public boolean isLoginRequired() { 207 211 return outgoingConfig.getUseAuth() > 0; 208 212 }
+7
LogicMail/src/org/logicprobe/LogicMail/ui/ConfigScreen.java
··· 105 105 private VerticalFieldManager networkingFieldManager; 106 106 private ObjectChoiceField networkTransportChoiceField; 107 107 private CheckboxField enableWiFiCheckboxField; 108 + private CheckboxField enableHandoverCheckboxField; 108 109 private CheckboxField overrideHostnameCheckboxField; 109 110 private BasicEditField localHostnameEditField; 110 111 ··· 396 397 resources.getString(LogicMailResource.CONFIG_GLOBAL_ENABLE_WIFI), 397 398 existingGlobalConfig.getEnableWiFi()); 398 399 400 + enableHandoverCheckboxField = new CheckboxField( 401 + resources.getString(LogicMailResource.CONFIG_GLOBAL_ENABLE_HANDOVER), 402 + existingGlobalConfig.isConnectionHandoverEnabled()); 403 + 399 404 boolean overrideHostname = localHostname.length() > 0; 400 405 overrideHostnameCheckboxField = new CheckboxField( 401 406 resources.getString(LogicMailResource.CONFIG_GLOBAL_OVERRIDE_HOSTNAME), ··· 423 428 Field.NON_FOCUSABLE | LabeledSeparatorField.TOP_BORDER | LabeledSeparatorField.BOTTOM_BORDER)); 424 429 networkingFieldManager.add(networkTransportChoiceField); 425 430 networkingFieldManager.add(enableWiFiCheckboxField); 431 + networkingFieldManager.add(enableHandoverCheckboxField); 426 432 networkingFieldManager.add(overrideHostnameCheckboxField); 427 433 networkingFieldManager.add(localHostnameEditField); 428 434 networkingFieldManager.add(new BlankSeparatorField(separatorHeight)); ··· 1083 1089 config.setTransportType(getTransportSetting(networkTransportChoiceField.getSelectedIndex())); 1084 1090 1085 1091 config.setEnableWiFi(enableWiFiCheckboxField.getChecked()); 1092 + config.setConnectionHandoverEnabled(enableHandoverCheckboxField.getChecked()); 1086 1093 1087 1094 config.setAutoStartupEnabled(autoStartupCheckboxField.getChecked()); 1088 1095
+10 -1
LogicMail/src/org/logicprobe/LogicMail/util/AbstractNetworkConnector.java
··· 82 82 } 83 83 84 84 public Connection open(ConnectionConfig connectionConfig) throws IOException { 85 + return open(connectionConfig, false); 86 + } 87 + 88 + public Connection open(ConnectionConfig connectionConfig, boolean forceWiFi) throws IOException { 85 89 this.serverName = connectionConfig.getServerName(); 86 90 this.serverPort = connectionConfig.getServerPort(); 87 91 this.useSSL = (connectionConfig.getServerSecurity() == ConnectionConfig.SECURITY_SSL); 88 92 89 - initalizeSelectedTransportSet(connectionConfig); 93 + if(forceWiFi) { 94 + transports = TRANSPORT_WIFI; 95 + } 96 + else { 97 + initalizeSelectedTransportSet(connectionConfig); 98 + } 90 99 91 100 try { 92 101 socket = openSocketConnection();
+10
LogicMail/src/org/logicprobe/LogicMail/util/NetworkConnector.java
··· 48 48 Connection open(ConnectionConfig connectionConfig) throws IOException; 49 49 50 50 /** 51 + * Open a new network connection, using the provided configuration. 52 + * 53 + * @param connectionConfig the connection configuration 54 + * @param forceWiFi true, if only WiFi should be attempted 55 + * @return the opened connection instance 56 + * @throws IOException Signals that an I/O exception has occurred. 57 + */ 58 + Connection open(ConnectionConfig connectionConfig, boolean forceWiFi) throws IOException; 59 + 60 + /** 51 61 * Returns a connection instance that has been switched into TLS mode, 52 62 * as is commonly done after sending a protocol-specific <tt>STARTTLS</tt> 53 63 * command to the server.
+26 -10
LogicMail/src/org/logicprobe/LogicMail/util/NetworkConnectorBB45.java
··· 42 42 import net.rim.device.api.system.WLANInfo; 43 43 44 44 import org.logicprobe.LogicMail.AppInfo; 45 + import org.logicprobe.LogicMail.LogicMailResource; 45 46 import org.logicprobe.LogicMail.conf.ConnectionConfig; 46 47 import org.logicprobe.LogicMail.conf.GlobalConfig; 47 48 ··· 53 54 protected boolean coverageTCP=false, coverageMDS=false, coverageWAP2=false, coverageWiFi=false; 54 55 55 56 private int connectionType; 57 + private Exception connectionException; 56 58 57 59 public NetworkConnectorBB45(GlobalConfig globalConfig, ConnectionConfig connectionConfig) { 58 60 super(globalConfig, connectionConfig); ··· 64 66 String urlBase = buildConnectionStringBase(); 65 67 66 68 SocketConnection connection = attemptToOpenConnection(urlBase); 69 + 70 + if(connection == null) { 71 + throw new WrappedIOException(resources.getString(LogicMailResource.ERROR_UNABLE_TO_OPEN_CONNECTION), connectionException); 72 + } 67 73 68 74 return connection; 69 75 } ··· 161 167 return urlBase; 162 168 } 163 169 164 - private SocketConnection attemptToOpenConnection(String urlBase) throws IOException { 170 + private SocketConnection attemptToOpenConnection(String urlBase) { 165 171 SocketConnection connection = null; 166 172 if(((transports & TRANSPORT_WIFI) != 0) && coverageWiFi) { 167 173 connection = attemptWiFi(urlBase); ··· 178 184 return connection; 179 185 } 180 186 181 - private SocketConnection attemptWiFi(String urlBase) throws IOException { 187 + private SocketConnection attemptWiFi(String urlBase) { 182 188 String connectStr = urlBase + ";interface=wifi"; 183 189 if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 184 190 EventLogger.logEvent(AppInfo.GUID, "Attempting WiFi".getBytes(), ··· 189 195 return socket; 190 196 } 191 197 192 - private SocketConnection attemptDirectTCP(String urlBase) throws IOException { 198 + private SocketConnection attemptDirectTCP(String urlBase) { 193 199 String connectStr = urlBase + ";deviceside=true"; 194 200 if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 195 201 EventLogger.logEvent(AppInfo.GUID, "Attempting Direct TCP".getBytes(), ··· 200 206 return socket; 201 207 } 202 208 203 - private SocketConnection attemptMDS(String urlBase) throws IOException { 209 + private SocketConnection attemptMDS(String urlBase) { 204 210 String connectStr = urlBase + ";deviceside=false"; 205 211 if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 206 212 EventLogger.logEvent(AppInfo.GUID, "Attempting MDS".getBytes(), ··· 211 217 return socket; 212 218 } 213 219 214 - private SocketConnection attemptWAP2(String urlBase) throws IOException { 220 + private SocketConnection attemptWAP2(String urlBase) { 215 221 String connectStr = urlBase + ";deviceside=true;ConnectionUID=" + srWAP2.getUid(); 216 222 if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 217 223 EventLogger.logEvent(AppInfo.GUID, "Attempting WAP2".getBytes(), ··· 222 228 return socket; 223 229 } 224 230 225 - private SocketConnection openSocket(String connectStr) throws IOException { 226 - SocketConnection socket = (SocketConnection) Connector.open( 227 - connectStr, 228 - Connector.READ_WRITE, true); 229 - setConnectionUrl(connectStr); 231 + private SocketConnection openSocket(String connectStr) { 232 + SocketConnection socket; 233 + try { 234 + socket = (SocketConnection) Connector.open( 235 + connectStr, 236 + Connector.READ_WRITE, true); 237 + setConnectionUrl(connectStr); 238 + } catch (Exception e) { 239 + connectionException = e; 240 + socket = null; 241 + if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 242 + EventLogger.logEvent(AppInfo.GUID, e.toString().getBytes(), 243 + EventLogger.DEBUG_INFO); 244 + } 245 + } 230 246 return socket; 231 247 } 232 248 }
+23
LogicMail/src/org/logicprobe/LogicMail/util/Queue.java
··· 69 69 tail = tail.next; 70 70 } 71 71 } 72 + 73 + /** 74 + * Pushes an element onto the head of the queue. 75 + * @param element The element 76 + * @throws NullPointerException if the item is null 77 + */ 78 + public void push(Object element) { 79 + if(element == null) { 80 + throw new NullPointerException(); 81 + } 82 + Node node = new Node(); 83 + node.item = element; 84 + 85 + if(head == null) { 86 + node.next = null; 87 + head = node; 88 + tail = head; 89 + } 90 + else { 91 + node.next = head; 92 + head = node; 93 + } 94 + } 72 95 73 96 /** 74 97 * Retrieves the element at the head of the queue.
+47
LogicMailTests/src/org/logicprobe/LogicMail/mail/MockIncomingMailClient.java
··· 188 188 } 189 189 } 190 190 191 + public static final MockMethod MTHD_GET_CONNECTION_TYPE = new MockMethod( 192 + MockIncomingMailClient.class, 193 + "MTHD_GET_CONNECTION_TYPE", 194 + new Class[]{}, 195 + new Class[]{}, 196 + Integer.class, 197 + true); 198 + public int getConnectionType() { 199 + try { 200 + Object[] args = new Object[0]; 201 + MethodInvocation mi = new MethodInvocation(MTHD_GET_CONNECTION_TYPE, this, args); 202 + getInvocationHandler().invoke(mi); 203 + Object retVal = mi.getReturnValue(); 204 + AMockObject.assertReturnNotNull(MTHD_GET_CONNECTION_TYPE, retVal); 205 + return ((Integer)retVal).intValue(); 206 + } catch (Throwable t) { 207 + if (t instanceof java.lang.Error) { throw (java.lang.Error)t; } 208 + if (t instanceof java.lang.RuntimeException) { throw (java.lang.RuntimeException)t; } 209 + throw new HammockException(t); 210 + } 211 + } 212 + 191 213 public static final MockMethod MTHD_GET_FOLDER_MESSAGES_$_ARRAY_INT_FOLDERMESSAGECALLBACK_MAILPROGRESSHANDLER = new MockMethod( 192 214 MockIncomingMailClient.class, 193 215 "MTHD_GET_FOLDER_MESSAGES_$_ARRAY_INT_FOLDERMESSAGECALLBACK_MAILPROGRESSHANDLER", ··· 960 982 getInvocationHandler().invoke(mi); 961 983 Object retVal = mi.getReturnValue(); 962 984 AMockObject.assertReturnNotNull(MTHD_OPEN, retVal); 985 + return ((Boolean)retVal).booleanValue(); 986 + } catch (Throwable t) { 987 + if (t instanceof java.lang.Error) { throw (java.lang.Error)t; } 988 + if (t instanceof java.lang.RuntimeException) { throw (java.lang.RuntimeException)t; } 989 + if (t instanceof java.io.IOException) { throw (java.io.IOException)t; } 990 + if (t instanceof org.logicprobe.LogicMail.mail.MailException) { throw (org.logicprobe.LogicMail.mail.MailException)t; } 991 + throw new HammockException(t); 992 + } 993 + } 994 + 995 + public static final MockMethod MTHD_OPEN_$_CONNECTION = new MockMethod( 996 + MockIncomingMailClient.class, 997 + "MTHD_OPEN_$_CONNECTION", 998 + new Class[]{org.logicprobe.LogicMail.util.Connection.class}, 999 + new Class[]{java.io.IOException.class, org.logicprobe.LogicMail.mail.MailException.class}, 1000 + Boolean.class, 1001 + true); 1002 + public boolean open(org.logicprobe.LogicMail.util.Connection arg0) throws java.io.IOException, org.logicprobe.LogicMail.mail.MailException { 1003 + try { 1004 + Object[] args = new Object[1]; 1005 + args[0] = arg0; 1006 + MethodInvocation mi = new MethodInvocation(MTHD_OPEN_$_CONNECTION, this, args); 1007 + getInvocationHandler().invoke(mi); 1008 + Object retVal = mi.getReturnValue(); 1009 + AMockObject.assertReturnNotNull(MTHD_OPEN_$_CONNECTION, retVal); 963 1010 return ((Boolean)retVal).booleanValue(); 964 1011 } catch (Throwable t) { 965 1012 if (t instanceof java.lang.Error) { throw (java.lang.Error)t; }
+3
LogicMailTests/src/org/logicprobe/LogicMail/mail/imap/ImapClientTest.java
··· 496 496 497 497 class TestNetworkConnector implements NetworkConnector { 498 498 public Connection open(ConnectionConfig connectionConfig) throws IOException { 499 + return open(connectionConfig, false); 500 + } 501 + public Connection open(ConnectionConfig connectionConfig, boolean forceWiFi) throws IOException { 499 502 Hamspy hamspy = new Hamspy(true); 500 503 SocketConnection stubSocket = new MockSocketConnection(hamspy); 501 504 hamspy.setStubExpectation(MockSocketConnection.MTHD_OPEN_DATA_INPUT_STREAM).setReturnValue(
+15
LogicMailTests/src/org/logicprobe/LogicMail/util/QueueTest.java
··· 79 79 assertTrue(expThrown); 80 80 } 81 81 82 + public void testPush() { 83 + instance.add(new Integer(1)); 84 + assertEquals(new Integer(1), instance.element()); 85 + instance.add(new Integer(2)); 86 + assertEquals(new Integer(1), instance.element()); 87 + instance.push(new Integer(10)); 88 + assertEquals(new Integer(10), instance.element()); 89 + 90 + assertEquals(new Integer(10), instance.remove()); 91 + assertEquals(new Integer(1), instance.remove()); 92 + assertEquals(new Integer(2), instance.remove()); 93 + } 94 + 82 95 public void testRemove() { 83 96 boolean expThrown = false; 84 97 try { ··· 131 144 132 145 suite.addTest(new QueueTest("add", new TestMethod() 133 146 { public void run(TestCase tc) {((QueueTest)tc).testAdd(); } })); 147 + suite.addTest(new QueueTest("push", new TestMethod() 148 + { public void run(TestCase tc) {((QueueTest)tc).testPush(); } })); 134 149 suite.addTest(new QueueTest("remove", new TestMethod() 135 150 { public void run(TestCase tc) {((QueueTest)tc).testRemove(); } })); 136 151 suite.addTest(new QueueTest("element", new TestMethod()