Changeset 698 for trunk/LogicMail/src/org/logicprobe
- Timestamp:
- 09/05/10 14:03:08 (17 months ago)
- Location:
- trunk/LogicMail/src/org/logicprobe/LogicMail
- Files:
-
- 3 added
- 1 deleted
- 10 edited
-
mail/MailClientFactory.java (modified) (4 diffs)
-
mail/imap/ImapClient.java (modified) (9 diffs)
-
mail/imap/ImapProtocol.java (modified) (2 diffs)
-
mail/pop/PopClient.java (modified) (10 diffs)
-
mail/pop/PopProtocol.java (modified) (1 diff)
-
mail/smtp/SmtpClient.java (modified) (9 diffs)
-
mail/smtp/SmtpProtocol.java (modified) (5 diffs)
-
util/AbstractNetworkConnector.java (added)
-
util/Connection.java (modified) (11 diffs)
-
util/ConnectionBB42.java (deleted)
-
util/NetworkConnector.java (added)
-
util/NetworkConnectorBB42.java (added)
-
util/UtilFactory.java (modified) (3 diffs)
-
util/UtilFactoryBB42.java (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/MailClientFactory.java
r256 r698 42 42 import org.logicprobe.LogicMail.mail.pop.PopClient; 43 43 import org.logicprobe.LogicMail.mail.smtp.SmtpClient; 44 import org.logicprobe.LogicMail.util.UtilFactory; 44 45 45 46 /** … … 48 49 */ 49 50 public class MailClientFactory { 50 private static Hashtable incomingClientTable = new Hashtable();51 private static Hashtable outgoingClientTable = new Hashtable();51 private static final Hashtable incomingClientTable = new Hashtable(); 52 private static final Hashtable outgoingClientTable = new Hashtable(); 52 53 53 54 private MailClientFactory() { } … … 67 68 GlobalConfig globalConfig = MailSettings.getInstance().getGlobalConfig(); 68 69 if(acctConfig instanceof PopConfig) { 69 client = new PopClient(globalConfig, (PopConfig)acctConfig); 70 client = new PopClient( 71 UtilFactory.getInstance().getNetworkConnector(globalConfig, acctConfig), 72 globalConfig, (PopConfig)acctConfig); 70 73 incomingClientTable.put(acctConfig, client); 71 74 } 72 75 else if(acctConfig instanceof ImapConfig) { 73 client = new ImapClient(globalConfig, (ImapConfig)acctConfig); 76 client = new ImapClient( 77 UtilFactory.getInstance().getNetworkConnector(globalConfig, acctConfig), 78 globalConfig, (ImapConfig)acctConfig); 74 79 incomingClientTable.put(acctConfig, client); 75 80 } … … 105 110 if(client == null) { 106 111 GlobalConfig globalConfig = MailSettings.getInstance().getGlobalConfig(); 107 client = new SmtpClient(globalConfig, outgoingConfig); 112 client = new SmtpClient( 113 UtilFactory.getInstance().getNetworkConnector(globalConfig, outgoingConfig), 114 globalConfig, outgoingConfig); 108 115 outgoingClientTable.put(outgoingConfig, client); 109 116 } -
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/imap/ImapClient.java
r694 r698 65 65 import org.logicprobe.LogicMail.message.UnsupportedPart; 66 66 import org.logicprobe.LogicMail.util.Connection; 67 import org.logicprobe.LogicMail.util. UtilFactory;67 import org.logicprobe.LogicMail.util.NetworkConnector; 68 68 import org.logicprobe.LogicMail.util.DataStore; 69 69 import org.logicprobe.LogicMail.util.DataStoreFactory; … … 75 75 */ 76 76 public class ImapClient extends AbstractIncomingMailClient { 77 private MailSettings mailSettings; 78 private ImapConfig accountConfig; 77 private final NetworkConnector networkConnector; 78 private final MailSettings mailSettings; 79 private final ImapConfig accountConfig; 80 private final ImapProtocol imapProtocol; 79 81 private Connection connection; 80 private ImapProtocol imapProtocol;81 82 private String username; 82 83 private String password; 83 84 private boolean openStarted; 84 private boolean configChanged;85 85 86 86 /** … … 132 132 private static String CAPABILITY_IDLE = "IDLE"; 133 133 134 public ImapClient(GlobalConfig globalConfig, ImapConfig accountConfig) { 134 public ImapClient(NetworkConnector networkConnector, GlobalConfig globalConfig, ImapConfig accountConfig) { 135 this.networkConnector = networkConnector; 135 136 this.accountConfig = accountConfig; 136 137 this.mailSettings = MailSettings.getInstance(); 137 connection = UtilFactory.getInstance().createConnection(accountConfig); 138 imapProtocol = new ImapProtocol(connection); 138 imapProtocol = new ImapProtocol(); 139 139 username = accountConfig.getServerUser(); 140 140 password = accountConfig.getServerPass(); 141 141 openStarted = false; 142 configChanged = false;143 142 mailSettings.addMailSettingsListener(mailSettingsListener); 144 143 } … … 165 164 username = accountConfig.getServerUser(); 166 165 password = accountConfig.getServerPass(); 167 168 if(!isConnected()) {169 // Rebuild the connection to include new settings170 connection = UtilFactory.getInstance().createConnection(accountConfig);171 imapProtocol = new ImapProtocol(connection);172 }173 else {174 // Set a flag to make sure we rebuild the Connection object175 // the next time we close the connection.176 configChanged = true;177 }178 166 } 179 167 } … … 185 173 try { 186 174 if(!openStarted) { 187 connection.open(); 175 connection = networkConnector.open(accountConfig); 176 imapProtocol.setConnection(connection); 177 188 178 activeMailbox = null; 189 179 190 180 // Swallow the initial "* OK" line from the server 191 181 connection.receive(); 192 182 193 183 // Find out server capabilities 194 184 capabilities = imapProtocol.executeCapability(); … … 202 192 || (serverSecurity == ConnectionConfig.SECURITY_TLS)) { 203 193 imapProtocol.executeStartTLS(); 204 connection.startTLS(); 194 connection = networkConnector.getConnectionAsTLS(connection); 195 imapProtocol.setConnection(connection); 205 196 } 206 197 … … 251 242 public void close() throws IOException, MailException { 252 243 if(connection.isConnected()) { 253 // Not closing to avoid expunging deleted messages 254 //if(activeMailbox != null && !activeMailbox.equals("")) { 255 // imapProtocol.executeClose(); 256 //} 244 // Note: Active mailbox is not closed to avoid unintentionally 245 // expunging deleted messages. 257 246 try { 258 247 imapProtocol.executeLogout(); … … 261 250 activeMailbox = null; 262 251 connection.close(); 263 264 if(configChanged) { 265 // Rebuild the connection to include new settings 266 connection = UtilFactory.getInstance().createConnection(accountConfig); 267 imapProtocol = new ImapProtocol(connection); 268 configChanged = false; 269 } 252 connection = null; 270 253 } 271 254 … … 274 257 */ 275 258 public boolean isConnected() { 276 return connection .isConnected();259 return connection != null && connection.isConnected(); 277 260 } 278 261 -
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/imap/ImapProtocol.java
r692 r698 49 49 import java.util.Vector; 50 50 51 52 51 /** 53 52 * This class implements the commands for the IMAP protocol 54 53 */ 55 54 public class ImapProtocol { 56 57 55 private Connection connection; 58 56 private String idleCommandTag; … … 65 63 66 64 /** Creates a new instance of ImapProtocol */ 67 public ImapProtocol(Connection connection) { 65 public ImapProtocol() { 66 } 67 68 /** 69 * Sets the connection instance used by this class. 70 * This must be set after opening the connection, and prior to calling any 71 * command methods. 72 * 73 * @param connection the new connection instance 74 */ 75 public void setConnection(Connection connection) { 68 76 this.connection = connection; 69 77 } 70 78 71 79 /** 72 80 * Execute the "STARTTLS" command. -
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/pop/PopClient.java
r658 r698 58 58 import org.logicprobe.LogicMail.message.MimeMessagePart; 59 59 import org.logicprobe.LogicMail.util.Connection; 60 import org.logicprobe.LogicMail.util. UtilFactory;60 import org.logicprobe.LogicMail.util.NetworkConnector; 61 61 import org.logicprobe.LogicMail.util.MailMessageParser; 62 62 import org.logicprobe.LogicMail.util.StringParser; … … 68 68 */ 69 69 public class PopClient extends AbstractIncomingMailClient { 70 private MailSettings mailSettings; 71 private GlobalConfig globalConfig; 72 private PopConfig accountConfig; 70 private final NetworkConnector networkConnector; 71 private final MailSettings mailSettings; 72 private final GlobalConfig globalConfig; 73 private final PopConfig accountConfig; 74 private final PopProtocol popProtocol; 73 75 private Connection connection; 74 private PopProtocol popProtocol;75 76 private String username; 76 77 private String password; 77 78 private boolean openStarted; 78 private boolean configChanged;79 79 80 80 /** … … 91 91 92 92 /** Creates a new instance of PopClient */ 93 public PopClient(GlobalConfig globalConfig, PopConfig accountConfig) { 93 public PopClient(NetworkConnector networkConnector, GlobalConfig globalConfig, PopConfig accountConfig) { 94 this.networkConnector = networkConnector; 94 95 this.globalConfig = globalConfig; 95 96 this.accountConfig = accountConfig; 96 97 this.mailSettings = MailSettings.getInstance(); 97 connection = UtilFactory.getInstance().createConnection(accountConfig); 98 popProtocol = new PopProtocol(connection); 98 popProtocol = new PopProtocol(); 99 99 username = accountConfig.getServerUser(); 100 100 password = accountConfig.getServerPass(); … … 104 104 activeMailbox.setMsgCount(0); 105 105 openStarted = false; 106 configChanged = false;107 106 mailSettings.addMailSettingsListener(mailSettingsListener); 108 107 } … … 129 128 username = accountConfig.getServerUser(); 130 129 password = accountConfig.getServerPass(); 131 132 if(!isConnected()) {133 // Rebuild the connection to include new settings134 connection = UtilFactory.getInstance().createConnection(accountConfig);135 popProtocol = new PopProtocol(connection);136 }137 else {138 // Set a flag to make sure we rebuild the Connection object139 // the next time we close the connection.140 configChanged = true;141 }142 130 } 143 131 } … … 162 150 public boolean open() throws IOException, MailException { 163 151 if(!openStarted) { 164 connection.open(); 152 connection = networkConnector.open(accountConfig); 153 popProtocol.setConnection(connection); 154 165 155 // Eat the initial server response 166 156 connection.receive(); … … 177 167 || (serverSecurity == ConnectionConfig.SECURITY_TLS)) { 178 168 if(popProtocol.executeStartTLS()) { 179 connection.startTLS(); 169 connection = networkConnector.getConnectionAsTLS(connection); 170 popProtocol.setConnection(connection); 180 171 } 181 172 else { … … 185 176 else if(capabilities == null && serverSecurity == ConnectionConfig.SECURITY_TLS_IF_AVAILABLE) { 186 177 if(popProtocol.executeStartTLS()) { 187 connection.startTLS(); 178 connection = networkConnector.getConnectionAsTLS(connection); 179 popProtocol.setConnection(connection); 188 180 } 189 181 } … … 213 205 } 214 206 connection.close(); 215 216 if(configChanged) { 217 // Rebuild the connection to include new settings 218 connection = UtilFactory.getInstance().createConnection(accountConfig); 219 popProtocol = new PopProtocol(connection); 220 configChanged = false; 221 } 207 connection = null; 222 208 } 223 209 … … 226 212 */ 227 213 public boolean isConnected() { 228 return connection .isConnected();214 return connection != null && connection.isConnected(); 229 215 } 230 216 -
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/pop/PopProtocol.java
r694 r698 49 49 50 50 /** Creates a new instance of PopProtocol */ 51 public PopProtocol(Connection connection) { 51 public PopProtocol() { 52 } 53 54 /** 55 * Sets the connection instance used by this class. 56 * This must be set after opening the connection, and prior to calling any 57 * command methods. 58 * 59 * @param connection the new connection instance 60 */ 61 public void setConnection(Connection connection) { 52 62 this.connection = connection; 53 63 } -
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/smtp/SmtpClient.java
r677 r698 44 44 import org.logicprobe.LogicMail.message.MessageMimeConverter; 45 45 import org.logicprobe.LogicMail.util.Connection; 46 import org.logicprobe.LogicMail.util. UtilFactory;46 import org.logicprobe.LogicMail.util.NetworkConnector; 47 47 import org.logicprobe.LogicMail.util.MailMessageParser; 48 48 … … 55 55 */ 56 56 public class SmtpClient implements OutgoingMailClient { 57 private final NetworkConnector networkConnector; 57 58 private final MailSettings mailSettings; 58 59 private final GlobalConfig globalConfig; 59 60 private final OutgoingConfig outgoingConfig; 61 private final SmtpProtocol smtpProtocol; 60 62 private String hostname; 61 63 private Connection connection; 62 private SmtpProtocol smtpProtocol;63 64 private boolean isFresh; 64 65 private boolean openStarted; 65 66 private String username; 66 67 private String password; 67 private boolean configChanged;68 68 69 69 /** … … 79 79 80 80 /** Creates a new instance of SmtpClient */ 81 public SmtpClient(GlobalConfig globalConfig, OutgoingConfig outgoingConfig) { 81 public SmtpClient(NetworkConnector networkConnector, GlobalConfig globalConfig, OutgoingConfig outgoingConfig) { 82 this.networkConnector = networkConnector; 82 83 this.globalConfig = globalConfig; 83 84 this.outgoingConfig = outgoingConfig; 84 85 this.mailSettings = MailSettings.getInstance(); 85 connection = UtilFactory.getInstance().createConnection(outgoingConfig); 86 smtpProtocol = new SmtpProtocol(connection); 86 smtpProtocol = new SmtpProtocol(); 87 87 88 88 if (outgoingConfig.getUseAuth() > 0) { … … 95 95 96 96 openStarted = false; 97 configChanged = false;98 97 mailSettings.addMailSettingsListener(mailSettingsListener); 99 98 } … … 114 113 username = outgoingConfig.getServerUser(); 115 114 password = outgoingConfig.getServerPass(); 116 117 if(!isConnected()) {118 // Rebuild the connection to include new settings119 connection = UtilFactory.getInstance().createConnection(outgoingConfig);120 smtpProtocol = new SmtpProtocol(connection);121 }122 else {123 // Set a flag to make sure we rebuild the Connection object124 // the next time we close the connection.125 configChanged = true;126 }127 115 } 128 116 } … … 130 118 public boolean open() throws IOException, MailException { 131 119 if (!openStarted) { 132 connection.open(); 120 connection = networkConnector.open(outgoingConfig); 121 smtpProtocol.setConnection(connection); 133 122 134 123 // Eat the initial server response … … 154 143 || (serverSecurity == ConnectionConfig.SECURITY_TLS)) { 155 144 smtpProtocol.executeStartTLS(); 156 connection.startTLS(); 145 connection = networkConnector.getConnectionAsTLS(connection); 146 smtpProtocol.setConnection(connection); 157 147 158 148 // Re-execute the EHLO command, since some servers require this … … 182 172 183 173 connection.close(); 184 185 if (configChanged) { 186 // Rebuild the connection to include new settings 187 connection = UtilFactory.getInstance().createConnection(outgoingConfig); 188 smtpProtocol = new SmtpProtocol(connection); 189 configChanged = false; 190 } 174 connection = null; 191 175 } 192 176 … … 196 180 197 181 public boolean isConnected() { 198 return connection .isConnected();182 return connection != null && connection.isConnected(); 199 183 } 200 184 -
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/smtp/SmtpProtocol.java
r689 r698 43 43 import org.logicprobe.LogicMail.util.Connection; 44 44 import org.logicprobe.LogicMail.util.MD5; 45 import org.logicprobe.LogicMail.util.StringParser;46 45 47 46 /** … … 49 48 */ 50 49 public class SmtpProtocol { 51 private finalConnection connection;50 private Connection connection; 52 51 53 52 /** Specifies the PLAIN authentication mechanism */ … … 61 60 62 61 /** Creates a new instance of SmtpProtocol */ 63 public SmtpProtocol(Connection connection) { 62 public SmtpProtocol() { 63 } 64 65 /** 66 * Sets the connection instance used by this class. 67 * This must be set after opening the connection, and prior to calling any 68 * command methods. 69 * 70 * @param connection the new connection instance 71 */ 72 public void setConnection(Connection connection) { 64 73 this.connection = connection; 65 74 } … … 140 149 141 150 result = execute(Base64OutputStream.encodeAsString(eval, 0, eval.length, false, false)); 142 if(!result.startsWith(CODE_235)) {143 return false;144 }145 }146 else if(mech == AUTH_DIGEST_MD5) {147 // Note: This code does not currently work correctly148 result = execute("AUTH DIGEST-MD5");149 if(!result.startsWith(CODE_334)) {150 throw new MailException(result.substring(4));151 }152 153 String challenge = new String(Base64InputStream.decode(result.substring(4)));154 System.err.println("-->Challenge: " + challenge);155 // Note, the fields with CSV string values will get mucked up156 String[] fields = StringParser.parseTokenString(challenge, ",");157 int i;158 String realm = null;159 String nonce = null;160 String qop = null;161 String algorithm = null;162 String charset = null;163 for(i = 0; i < fields.length; i++) {164 if(fields[i].startsWith("realm")) {165 realm = parseValue(fields[i]);166 }167 else if(fields[i].startsWith("nonce")) {168 nonce = parseValue(fields[i]);169 }170 else if(fields[i].startsWith("qop")) {171 qop = parseValue(fields[i]);172 }173 else if(fields[i].startsWith("algorithm")) {174 algorithm = parseValue(fields[i]);175 }176 else if(fields[i].startsWith("charset")) {177 charset = parseValue(fields[i]);178 }179 }180 System.err.println("--> Realm: "+realm);181 System.err.println("--> Nonce: "+nonce);182 System.err.println("--> Qop: "+qop);183 System.err.println("--> Algorithm: "+algorithm);184 System.err.println("--> Charset: "+charset);185 186 StringBuffer buf = new StringBuffer();187 MD5 md5 = new MD5();188 // Generate the response189 // If authzid is not specified, then A1 is:190 // A1 = { H( { username-value, ":", realm-value, ":", passwd } ),191 // ":", nonce-value, ":", cnonce-value }192 buf.append(username);193 buf.append(':');194 buf.append(realm);195 buf.append(':');196 buf.append(password);197 md5.update(buf.toString().getBytes(charset));198 String A1 = byteArrayToHexString(md5.getDigest()); // HEX(H(A1))199 System.err.println("A1: HEX(H( { "+buf.toString()+" )) = " + A1);200 201 // If the "qop" directive's value is "auth", then A2 is:202 // A2 = { "AUTHENTICATE:", digest-uri-value }203 buf = new StringBuffer();204 md5.reset();205 buf.append("AUTHENTICATE:");206 buf.append("smtp/");207 buf.append(connection.getServerName());208 md5.update(buf.toString().getBytes(charset));209 String A2 = byteArrayToHexString(md5.getDigest()); // HEX(H(A2))210 System.err.println("A2: HEX(H("+buf.toString()+")) = " + A2);211 212 String cnonce = "K4esOhbue3/urOGXWiEivkF9WUeZziawEHFC9nEz4BA=";213 String nc = "00000001";214 215 //HEX( KD ( HEX(H(A1)),216 // { nonce-value, ":" nc-value, ":",217 // cnonce-value, ":", qop-value, ":", HEX(H(A2)) }))218 buf = new StringBuffer();219 md5.reset();220 buf.append(A1);221 buf.append(':');222 buf.append(nonce);223 buf.append(':');224 buf.append(nc);225 buf.append(':');226 buf.append(cnonce);227 buf.append(':');228 buf.append("auth");229 buf.append(':');230 buf.append(A2);231 md5.update(buf.toString().getBytes(charset));232 String resp = byteArrayToHexString(md5.getDigest());233 System.err.println("HEX(MD5("+buf.toString()+")) = " + resp);234 235 // Craft the reply236 buf = new StringBuffer();237 buf.append("charset="+charset+",");238 buf.append("username=\""+username+"\",");239 buf.append("realm=\""+realm+"\",");240 buf.append("nonce=\""+nonce+"\",");241 buf.append("nc="+nc+",");242 buf.append("cnonce=\""+cnonce+"\",");243 buf.append("digest-uri=\"smtp/"+connection.getServerName()+"\",");244 buf.append("response="+resp+",");245 buf.append("qop=auth");246 System.err.println("-->Response: " + buf.toString());247 byte[] response = buf.toString().getBytes(charset);248 result = execute(Base64OutputStream.encodeAsString(response, 0, response.length, false, false));249 if(!result.startsWith(CODE_334)) {250 return false;251 }252 System.err.println("-->Result: "+(new String(Base64InputStream.decode(result))));253 151 if(!result.startsWith(CODE_235)) { 254 152 return false; … … 488 386 489 387 return digest; 490 }491 492 private static String parseValue(String input) {493 int p, q;494 p = input.indexOf('=') + 1;495 q = input.length() - 1;496 if(q <= p) {497 return null;498 }499 if(input.charAt(p) == '\"') {500 p++;501 }502 if(input.charAt(q) == '\"') {503 q--;504 }505 return input.substring(p, q+1);506 388 } 507 389 -
trunk/LogicMail/src/org/logicprobe/LogicMail/util/Connection.java
r696 r698 32 32 package org.logicprobe.LogicMail.util; 33 33 34 import net.rim.device.api.crypto.tls.tls10.TLS10Connection;35 import net.rim.device.api.i18n.ResourceBundle;36 34 import net.rim.device.api.io.NoCopyByteArrayOutputStream; 37 35 import net.rim.device.api.system.EventLogger; 38 36 import net.rim.device.api.util.Arrays; 39 import net.rim.device.cldc.io.ssl.TLSException;40 37 41 38 import org.logicprobe.LogicMail.AppInfo; 42 import org.logicprobe.LogicMail.LogicMailResource;43 import org.logicprobe.LogicMail.conf.ConnectionConfig;44 39 import org.logicprobe.LogicMail.conf.GlobalConfig; 45 40 import org.logicprobe.LogicMail.conf.MailSettings; 46 41 47 42 import java.io.ByteArrayOutputStream; 48 import java.io.DataInputStream;49 import java.io.DataOutputStream;50 43 import java.io.IOException; 51 44 import java.io.InputStream; … … 53 46 54 47 import javax.microedition.io.SocketConnection; 55 import javax.microedition.io.StreamConnection;56 48 57 49 58 50 /** 59 * This is the abstract base class for socket connections used inside the SMTP, 60 * POP3, and IMAP protocols of the mail package. It handles the details of 61 * sending data in what ever manner is appropriate to the mail protocol, and 62 * receiving data in whole lines. The specifics of opening network connections 63 * on the BlackBerry platform is delegated to subclasses. 51 * This class serves as a facade for socket connections used by the various 52 * protocols supported by this application. It handles the details of sending 53 * and receiving data in whole lines, with customizable logic to meet protocol 54 * specific needs. 64 55 */ 65 public abstract class Connection { 66 protected static ResourceBundle resources = ResourceBundle.getBundle(LogicMailResource.BUNDLE_ID, LogicMailResource.BUNDLE_NAME); 67 68 /** Select everything except WiFi */ 69 protected static final int TRANSPORT_AUTO = 0xFE; 70 /** Select WiFi */ 71 protected static final int TRANSPORT_WIFI = 0x01; 72 /** Select Direct TCP */ 73 protected static final int TRANSPORT_DIRECT_TCP = 0x02; 74 /** Select MDS */ 75 protected static final int TRANSPORT_MDS = 0x04; 76 /** Select WAP 2.0 */ 77 protected static final int TRANSPORT_WAP2 = 0x08; 78 56 public class Connection { 79 57 private static final byte CR = (byte)0x0D; 80 58 private static final byte LF = (byte)0x0A; … … 82 60 private static String strCRLF = "\r\n"; 83 61 84 private UtilFactory utilFactory; 85 protected String serverName; 86 protected int serverPort; 87 protected boolean useSSL; 88 protected int transports; 89 private StreamConnection socket; 62 private SocketConnection socket; 90 63 private String localAddress; 91 private String connectionUrl; 92 protected GlobalConfig globalConfig; 93 protected boolean useWiFi; 64 private GlobalConfig globalConfig; 94 65 private InputStream input; 95 66 private OutputStream output; … … 114 85 * Initializes a new connection object. 115 86 * 116 * @param connectionConfig Configuration data for the connection 117 */ 118 protected Connection(ConnectionConfig connectionConfig) { 87 * @param socket Socket representing the connection 88 * @throws IOException Thrown if an I/O error occurs 89 */ 90 protected Connection(SocketConnection socket) throws IOException { 119 91 this.globalConfig = MailSettings.getInstance().getGlobalConfig(); 120 this.utilFactory = UtilFactory.getInstance(); 121 122 this.serverName = connectionConfig.getServerName(); 123 this.serverPort = connectionConfig.getServerPort(); 124 this.useSSL = (connectionConfig.getServerSecurity() == ConnectionConfig.SECURITY_SSL); 125 126 int transportType; 127 boolean enableWiFi; 128 if(connectionConfig.getTransportType() == ConnectionConfig.TRANSPORT_GLOBAL) { 129 transportType = globalConfig.getTransportType(); 130 enableWiFi = globalConfig.getEnableWiFi(); 131 } 132 else { 133 transportType = connectionConfig.getTransportType(); 134 enableWiFi = connectionConfig.getEnableWiFi(); 135 } 136 137 // Populate the bit-flags for the selected transport types 138 // based on the configuration parameters. 139 switch(transportType) { 140 case ConnectionConfig.TRANSPORT_WIFI_ONLY: 141 transports = Connection.TRANSPORT_WIFI; 142 break; 143 case ConnectionConfig.TRANSPORT_AUTO: 144 transports = Connection.TRANSPORT_AUTO; 145 break; 146 case ConnectionConfig.TRANSPORT_DIRECT_TCP: 147 transports = Connection.TRANSPORT_DIRECT_TCP; 148 break; 149 case ConnectionConfig.TRANSPORT_MDS: 150 transports = Connection.TRANSPORT_MDS; 151 break; 152 case ConnectionConfig.TRANSPORT_WAP2: 153 transports = Connection.TRANSPORT_WAP2; 154 break; 155 default: 156 // Should only get here in rare cases of invalid configuration 157 // data, so we select full automatic with WiFi. 158 transports = Connection.TRANSPORT_AUTO; 159 enableWiFi = true; 160 break; 161 } 162 if(enableWiFi) { transports |= Connection.TRANSPORT_WIFI; } 163 164 this.input = null; 165 this.output = null; 166 this.socket = null; 167 } 168 169 /** 170 * Opens a connection. 171 */ 172 public void open() throws IOException { 173 if ((input != null) || (output != null) || (socket != null)) { 174 close(); 175 } 176 177 utilFactory.addOpenConnection(this); 178 179 synchronized(socketLock) { 180 socket = openStreamConnection(); 181 if(socket == null) { 182 throw new IOException(resources.getString(LogicMailResource.ERROR_UNABLE_TO_OPEN_CONNECTION)); 183 } 184 185 input = socket.openDataInputStream(); 186 output = socket.openDataOutputStream(); 187 localAddress = ((SocketConnection) socket).getLocalAddress(); 188 bytesSent = 0; 189 bytesReceived = 0; 190 } 191 192 if (EventLogger.getMinimumLevel() >= EventLogger.INFORMATION) { 193 String msg = "Connection established:\r\n" + "Socket: " + 194 socket.getClass().toString() + strCRLF + "Local address: " + 195 localAddress + strCRLF; 196 EventLogger.logEvent(AppInfo.GUID, msg.getBytes(), 197 EventLogger.INFORMATION); 198 } 199 } 200 201 /** 202 * Open a stream connection. 203 * This method should encapsulate all platform-specific logic for opening 204 * network connections. If the connection is successfully opened, this 205 * method should also call {@link #setConnectionUrl(String)} to set the 206 * chosen connection string. 207 * 208 * @return the stream connection 209 * 210 * @throws IOException Signals that an I/O exception has occurred. 211 */ 212 protected abstract StreamConnection openStreamConnection() throws IOException; 213 214 /** 215 * Sets the connection string used to open the current connection. 216 * 217 * @param connectionUrl the new connection string 218 */ 219 protected void setConnectionUrl(String connectionUrl) { 220 this.connectionUrl = connectionUrl; 221 } 222 223 /** 224 * Gets the connection string used to open the current connection. 225 * 226 * @return the connection string 227 */ 228 public String getConnectionUrl() { 229 return connectionUrl; 92 93 this.socket = socket; 94 this.input = socket.openDataInputStream(); 95 this.output = socket.openDataOutputStream(); 96 this.localAddress = socket.getLocalAddress(); 97 this.bytesSent = 0; 98 this.bytesReceived = 0; 230 99 } 231 100 … … 233 102 * Closes a connection. 234 103 */ 235 public void close() throws IOException{104 public void close() { 236 105 synchronized(socketLock) { 237 106 try { 238 if (input != null) { 239 input.close(); 240 input = null; 241 } 107 input.close(); 108 output.close(); 109 socket.close(); 242 110 } catch (Exception exp) { 111 EventLogger.logEvent(AppInfo.GUID, 112 ("Error closing connection: " + exp.getMessage()).getBytes(), 113 EventLogger.WARNING); 114 } finally { 243 115 input = null; 244 }245 246 try {247 if (output != null) {248 output.close();249 output = null;250 }251 } catch (Exception exp) {252 116 output = null; 253 }254 255 try {256 if (socket != null) {257 socket.close();258 socket = null;259 }260 } catch (Exception exp) {261 117 socket = null; 262 118 } 263 setConnectionUrl(null); 264 } 265 266 utilFactory.removeOpenConnection(this); 119 } 267 120 268 121 EventLogger.logEvent(AppInfo.GUID, "Connection closed".getBytes(), … … 288 141 public String getLocalAddress() { 289 142 return localAddress; 290 }291 292 /**293 * Get the server name used when this connection was created294 * @return Server name295 */296 public String getServerName() {297 return serverName;298 143 } 299 144 … … 327 172 328 173 /** 174 * Gets the socket used by this connection instance. 175 * This method should only be called by <code>NetworkConnector</code> 176 * for the purpose of creating new wrapped sockets. 177 * 178 * @return the connection socket 179 */ 180 SocketConnection getSocket() { 181 return socket; 182 } 183 184 /** 185 * Gets the input stream used by this connection instance. 186 * This method should only be called by <code>NetworkConnector</code> 187 * for the purpose of creating new wrapped sockets. 188 * 189 * @return the connection socket's input stream 190 */ 191 InputStream getInput() { 192 return input; 193 } 194 195 /** 196 * Gets the output stream used by this connection instance. 197 * This method should only be called by <code>NetworkConnector</code> 198 * for the purpose of creating new wrapped sockets. 199 * 200 * @return the connection socket's output stream 201 */ 202 OutputStream getOutput() { 203 return output; 204 } 205 206 /** 329 207 * Sends a string to the server, terminating it with a CRLF. 330 208 * No cleanup is performed, as it is expected that the string … … 382 260 */ 383 261 public int available() throws IOException { 384 if (fakeAvailable == -1) { 385 return input.available(); 386 } else { 387 return fakeAvailable; 262 synchronized(socketLock) { 263 if (fakeAvailable == -1) { 264 return input.available(); 265 } else { 266 return fakeAvailable; 267 } 388 268 } 389 269 } … … 401 281 return receive(lineResponseTester); 402 282 } 403 404 283 405 284 /** … … 471 350 EventLogger.INFORMATION); 472 351 473 try { 474 close(); 475 } catch (IOException e) { } 352 close(); 476 353 477 354 throw new IOException("Connection closed"); … … 548 425 }; 549 426 }; 550 551 /**552 * Switches the underlying connection to SSL mode, as commonly done after553 * sending a <tt>STARTTLS</tt> command to the server.554 *555 * @throws IOException Signals that an I/O exception has occurred.556 */557 public void startTLS() throws IOException {558 synchronized(socketLock) {559 // Shortcut the method if we're already in SSL mode560 if(socket instanceof TLS10Connection) { return; }561 562 if(socket == null || connectionUrl == null) {563 throw new IOException("Connection has not been opened");564 }565 566 try {567 TLS10Connection tlsSocket = new TLS10Connection(568 new StreamConnectionWrapper(569 socket,570 (DataInputStream)input,571 (DataOutputStream)output),572 connectionUrl,573 true);574 575 socket = tlsSocket;576 input = socket.openDataInputStream();577 output = socket.openDataOutputStream();578 } catch (IOException e) {579 EventLogger.logEvent(AppInfo.GUID,580 ("Unable to switch to TLS mode: " + e.getMessage()).getBytes(), EventLogger.ERROR);581 throw new IOException("Unable to switch to TLS mode");582 } catch (TLSException e) {583 EventLogger.logEvent(AppInfo.GUID,584 ("Unable to switch to TLS mode: " + e.getMessage()).getBytes(), EventLogger.ERROR);585 throw new IOException("Unable to switch to TLS mode");586 }587 }588 }589 590 /**591 * Decorator to wrap an existing stream connection so its I/O streams592 * can be reopened without throwing exceptions.593 */594 private static class StreamConnectionWrapper implements StreamConnection {595 private StreamConnection stream;596 private DataInputStream dataInputStream;597 private DataOutputStream dataOutputStream;598 599 public StreamConnectionWrapper(StreamConnection stream, DataInputStream dataInputStream, DataOutputStream dataOutputStream) {600 this.stream = stream;601 this.dataInputStream = dataInputStream;602 this.dataOutputStream = dataOutputStream;603 }604 605 public DataInputStream openDataInputStream() throws IOException {606 return dataInputStream;607 }608 public InputStream openInputStream() throws IOException {609 return dataInputStream;610 }611 public void close() throws IOException {612 stream.close();613 }614 public DataOutputStream openDataOutputStream() throws IOException {615 return dataOutputStream;616 }617 public OutputStream openOutputStream() throws IOException {618 return dataOutputStream;619 }620 }621 427 } -
trunk/LogicMail/src/org/logicprobe/LogicMail/util/UtilFactory.java
r614 r698 31 31 package org.logicprobe.LogicMail.util; 32 32 33 import java.io.IOException;34 import java.util.Vector;35 36 33 import org.logicprobe.LogicMail.conf.ConnectionConfig; 34 import org.logicprobe.LogicMail.conf.GlobalConfig; 37 35 38 36 /** … … 53 51 }; 54 52 55 private Vector openConnections = new Vector();56 57 53 /** 58 54 * Gets the single instance of UtilFactory. … … 70 66 } 71 67 72 void addOpenConnection(Connection connection) {73 synchronized (openConnections) {74 if (!openConnections.contains(connection)) {75 openConnections.addElement(connection);76 }77 }78 }79 80 void removeOpenConnection(Connection connection) {81 synchronized (openConnections) {82 if (openConnections.contains(connection)) {83 openConnections.removeElement(connection);84 }85 }86 }87 88 68 /** 89 * Determine whether open connections exist90 * 91 * @return True if there are open connections69 * Gets the connector used to open network connections. 70 * 71 * @return platform-specific connector instance 92 72 */ 93 public boolean hasOpenConnections() { 94 boolean result; 95 96 synchronized (openConnections) { 97 result = !openConnections.isEmpty(); 98 } 99 100 return result; 101 } 102 103 /** 104 * Close all open connections 105 */ 106 public void closeAllConnections() { 107 synchronized (openConnections) { 108 int size = openConnections.size(); 109 110 for (int i = 0; i < size; i++) { 111 try { 112 ((Connection) openConnections.elementAt(i)).close(); 113 } catch (IOException e) { } 114 } 115 116 openConnections.removeAllElements(); 117 } 118 } 119 120 /** 121 * Creates a new connection object. 122 * 123 * connectionConfig Configuration data for the connection 124 * 125 * @return the connection object 126 */ 127 public abstract Connection createConnection(ConnectionConfig connectionConfig); 73 public abstract NetworkConnector getNetworkConnector(GlobalConfig globalConfig, ConnectionConfig connectionConfig); 128 74 } -
trunk/LogicMail/src/org/logicprobe/LogicMail/util/UtilFactoryBB42.java
r608 r698 32 32 33 33 import org.logicprobe.LogicMail.conf.ConnectionConfig; 34 import org.logicprobe.LogicMail.conf.GlobalConfig; 34 35 35 36 public class UtilFactoryBB42 extends UtilFactory { … … 38 39 } 39 40 40 /* (non-Javadoc) 41 * @see org.logicprobe.LogicMail.util.UtilFactory#createConnection(org.logicprobe.LogicMail.conf.ConnectionConfig) 42 */ 43 public Connection createConnection(ConnectionConfig connectionConfig) { 44 return new ConnectionBB42(connectionConfig); 41 public NetworkConnector getNetworkConnector(GlobalConfig globalConfig, ConnectionConfig connectionConfig) { 42 return new NetworkConnectorBB42(globalConfig, connectionConfig); 45 43 } 46 44 }
Note: See TracChangeset
for help on using the changeset viewer.
