| 1 | /*- |
|---|
| 2 | * Copyright (c) 2009, 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.model; |
|---|
| 32 | |
|---|
| 33 | import java.io.DataInputStream; |
|---|
| 34 | import java.io.DataOutputStream; |
|---|
| 35 | import java.io.IOException; |
|---|
| 36 | import java.util.Enumeration; |
|---|
| 37 | import java.util.Hashtable; |
|---|
| 38 | import java.util.Vector; |
|---|
| 39 | |
|---|
| 40 | import javax.microedition.io.Connector; |
|---|
| 41 | import javax.microedition.io.file.FileConnection; |
|---|
| 42 | |
|---|
| 43 | import net.rim.device.api.system.EventLogger; |
|---|
| 44 | import net.rim.device.api.util.InvertedOrderComparator; |
|---|
| 45 | import net.rim.device.api.util.SimpleSortingVector; |
|---|
| 46 | |
|---|
| 47 | import org.logicprobe.LogicMail.AppInfo; |
|---|
| 48 | import org.logicprobe.LogicMail.conf.GlobalConfig; |
|---|
| 49 | import org.logicprobe.LogicMail.conf.MailSettings; |
|---|
| 50 | import org.logicprobe.LogicMail.conf.MailSettingsEvent; |
|---|
| 51 | import org.logicprobe.LogicMail.conf.MailSettingsListener; |
|---|
| 52 | import org.logicprobe.LogicMail.mail.MessageToken; |
|---|
| 53 | import org.logicprobe.LogicMail.message.MimeMessageContent; |
|---|
| 54 | import org.logicprobe.LogicMail.util.StringParser; |
|---|
| 55 | |
|---|
| 56 | /** |
|---|
| 57 | * Front-end for reading and writing messages from local file storage. |
|---|
| 58 | */ |
|---|
| 59 | public class MailFileManager { |
|---|
| 60 | private static MailFileManager instance; |
|---|
| 61 | private MailSettings mailSettings; |
|---|
| 62 | private String cacheUrl; |
|---|
| 63 | |
|---|
| 64 | private static String CACHE_PREFIX = "cache/"; |
|---|
| 65 | private static String MSG_SUFFIX = ".msg"; |
|---|
| 66 | private static String MSG_FILTER = "*.msg"; |
|---|
| 67 | private static String LOCAL_ACCOUNT_UID = "local"; |
|---|
| 68 | private static String LOCAL_OUTBOX_UID = "Outbox"; |
|---|
| 69 | |
|---|
| 70 | /** |
|---|
| 71 | * Instantiates a new mail file manager. |
|---|
| 72 | */ |
|---|
| 73 | private MailFileManager() { |
|---|
| 74 | mailSettings = MailSettings.getInstance(); |
|---|
| 75 | |
|---|
| 76 | // Register a listener for configuration changes |
|---|
| 77 | mailSettings.addMailSettingsListener(new MailSettingsListener() { |
|---|
| 78 | public void mailSettingsSaved(MailSettingsEvent e) { |
|---|
| 79 | if((e.getGlobalChange() & GlobalConfig.CHANGE_TYPE_DATA) != 0) { |
|---|
| 80 | refreshConfiguration(); |
|---|
| 81 | } |
|---|
| 82 | } |
|---|
| 83 | }); |
|---|
| 84 | |
|---|
| 85 | refreshConfiguration(); |
|---|
| 86 | } |
|---|
| 87 | |
|---|
| 88 | /** |
|---|
| 89 | * Gets the single instance of MailFileManager. |
|---|
| 90 | * |
|---|
| 91 | * @return single instance of MailFileManager |
|---|
| 92 | */ |
|---|
| 93 | public static synchronized MailFileManager getInstance() { |
|---|
| 94 | if(instance == null) { |
|---|
| 95 | instance = new MailFileManager(); |
|---|
| 96 | } |
|---|
| 97 | return instance; |
|---|
| 98 | } |
|---|
| 99 | |
|---|
| 100 | /** |
|---|
| 101 | * Refreshes the configuration based on any system configuration changes. |
|---|
| 102 | */ |
|---|
| 103 | synchronized void refreshConfiguration() { |
|---|
| 104 | String localDataLocation = mailSettings.getGlobalConfig().getLocalDataLocation(); |
|---|
| 105 | String newCacheUrl = localDataLocation + CACHE_PREFIX; |
|---|
| 106 | if(!newCacheUrl.equals(cacheUrl)) { |
|---|
| 107 | FileConnection fileConnection; |
|---|
| 108 | try { |
|---|
| 109 | fileConnection = (FileConnection)Connector.open(localDataLocation); |
|---|
| 110 | if(!fileConnection.exists()) { |
|---|
| 111 | fileConnection.mkdir(); |
|---|
| 112 | } |
|---|
| 113 | fileConnection.close(); |
|---|
| 114 | |
|---|
| 115 | fileConnection = (FileConnection)Connector.open(newCacheUrl); |
|---|
| 116 | if(!fileConnection.exists()) { |
|---|
| 117 | fileConnection.mkdir(); |
|---|
| 118 | } |
|---|
| 119 | fileConnection.close(); |
|---|
| 120 | cacheUrl = newCacheUrl; |
|---|
| 121 | } catch (IOException e) { |
|---|
| 122 | EventLogger.logEvent(AppInfo.GUID, |
|---|
| 123 | ("Unable to open cache: " + newCacheUrl |
|---|
| 124 | + "\r\n" + e.getMessage()).getBytes(), |
|---|
| 125 | EventLogger.ERROR); |
|---|
| 126 | cacheUrl = null; |
|---|
| 127 | } |
|---|
| 128 | } |
|---|
| 129 | } |
|---|
| 130 | |
|---|
| 131 | /** |
|---|
| 132 | * Write a message node to local storage. |
|---|
| 133 | * If data already exists matching the file path convention for the provided |
|---|
| 134 | * message, it will be overwritten. |
|---|
| 135 | * |
|---|
| 136 | * @param messageNode the message node |
|---|
| 137 | * |
|---|
| 138 | * @throws IOException Signals that an I/O exception has occurred. |
|---|
| 139 | */ |
|---|
| 140 | public synchronized void writeMessage(MessageNode messageNode) throws IOException { |
|---|
| 141 | if(cacheUrl == null) { return; } |
|---|
| 142 | |
|---|
| 143 | // Create a file connection for the message |
|---|
| 144 | FileConnection fileConnection = getMailboxFileConnection(messageNode.getParent()); |
|---|
| 145 | String url = fileConnection.getURL(); |
|---|
| 146 | fileConnection.close(); |
|---|
| 147 | fileConnection = (FileConnection)Connector.open( |
|---|
| 148 | url |
|---|
| 149 | + messageNode.getMessageToken().getMessageUid() |
|---|
| 150 | + MSG_SUFFIX); |
|---|
| 151 | if(fileConnection.exists()) { |
|---|
| 152 | fileConnection.truncate(0); |
|---|
| 153 | } |
|---|
| 154 | else { |
|---|
| 155 | fileConnection.create(); |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | // Create the writer |
|---|
| 159 | DataOutputStream output = fileConnection.openDataOutputStream(); |
|---|
| 160 | MessageNodeWriter writer = new MessageNodeWriter(output); |
|---|
| 161 | |
|---|
| 162 | // Write the node |
|---|
| 163 | writer.write(messageNode); |
|---|
| 164 | |
|---|
| 165 | // Close and cleanup |
|---|
| 166 | output.close(); |
|---|
| 167 | fileConnection.close(); |
|---|
| 168 | } |
|---|
| 169 | |
|---|
| 170 | /** |
|---|
| 171 | * Read message tokens for all the messages contained within the local |
|---|
| 172 | * storage location backing the provided mailbox node. |
|---|
| 173 | * |
|---|
| 174 | * @param mailboxNode the mailbox node |
|---|
| 175 | * |
|---|
| 176 | * @return the message tokens |
|---|
| 177 | * |
|---|
| 178 | * @throws IOException Signals that an I/O exception has occurred. |
|---|
| 179 | */ |
|---|
| 180 | public synchronized MessageToken[] readMessageTokens(MailboxNode mailboxNode) throws IOException { |
|---|
| 181 | if(cacheUrl == null) { return new MessageToken[0]; } |
|---|
| 182 | |
|---|
| 183 | //TODO: Implement an indexing mechanism to avoid listing the whole directory |
|---|
| 184 | //TODO: Provide support for partial listing requests |
|---|
| 185 | |
|---|
| 186 | Vector messageTokenList = new Vector(); |
|---|
| 187 | |
|---|
| 188 | String[] fileUrls = getMessageFiles(mailboxNode); |
|---|
| 189 | for(int i=0; i<fileUrls.length; i++) { |
|---|
| 190 | MessageToken messageToken = readMessageToken(fileUrls[i]); |
|---|
| 191 | if(messageToken != null) { |
|---|
| 192 | messageTokenList.addElement(messageToken); |
|---|
| 193 | } |
|---|
| 194 | } |
|---|
| 195 | |
|---|
| 196 | MessageToken[] result = new MessageToken[messageTokenList.size()]; |
|---|
| 197 | messageTokenList.copyInto(result); |
|---|
| 198 | return result; |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | public synchronized MessageNode[] readMessageNodes(MailboxNode mailboxNode) throws IOException { |
|---|
| 202 | return readMessageNodes(mailboxNode, false); |
|---|
| 203 | } |
|---|
| 204 | |
|---|
| 205 | public synchronized MessageNode[] readMessageNodes(MailboxNode mailboxNode, boolean loadContent) throws IOException { |
|---|
| 206 | if(cacheUrl == null) { return new MessageNode[0]; } |
|---|
| 207 | |
|---|
| 208 | Vector messageNodeList = new Vector(); |
|---|
| 209 | |
|---|
| 210 | String[] fileUrls = getMessageFiles(mailboxNode); |
|---|
| 211 | for(int i=0; i<fileUrls.length; i++) { |
|---|
| 212 | MessageNode messageNode = readMessageNode(fileUrls[i]); |
|---|
| 213 | if(messageNode != null) { |
|---|
| 214 | if(loadContent) { |
|---|
| 215 | MimeMessageContent[] content = readMessageContent(mailboxNode, messageNode.getMessageToken()); |
|---|
| 216 | messageNode.putMessageContent(content); |
|---|
| 217 | } |
|---|
| 218 | messageNodeList.addElement(messageNode); |
|---|
| 219 | } |
|---|
| 220 | } |
|---|
| 221 | |
|---|
| 222 | MessageNode[] result = new MessageNode[messageNodeList.size()]; |
|---|
| 223 | messageNodeList.copyInto(result); |
|---|
| 224 | return result; |
|---|
| 225 | } |
|---|
| 226 | |
|---|
| 227 | public synchronized void readMessageNodes(MailboxNode mailboxNode, MessageNodeCallback callback) throws IOException { |
|---|
| 228 | readMessageNodes(mailboxNode, false, callback); |
|---|
| 229 | } |
|---|
| 230 | |
|---|
| 231 | public synchronized void readMessageNodes(MailboxNode mailboxNode, boolean loadContent, MessageNodeCallback callback) throws IOException { |
|---|
| 232 | if(cacheUrl == null) { callback.messageNodeUpdated(null); } |
|---|
| 233 | |
|---|
| 234 | String[] fileUrls = getMessageFiles(mailboxNode); |
|---|
| 235 | Vector fileUrlsToLoad = new Vector(fileUrls.length); |
|---|
| 236 | for(int i=0; i<fileUrls.length; i++) { |
|---|
| 237 | int p = fileUrls[i].lastIndexOf('/'); |
|---|
| 238 | int q = fileUrls[i].lastIndexOf('.'); |
|---|
| 239 | if(p != -1 && q != -1 && p < q) { |
|---|
| 240 | String messageUid = fileUrls[i].substring(p + 1, q); |
|---|
| 241 | if(callback.messageNodeAvailable(messageUid)) { |
|---|
| 242 | fileUrlsToLoad.addElement(fileUrls[i]); |
|---|
| 243 | } |
|---|
| 244 | } |
|---|
| 245 | } |
|---|
| 246 | |
|---|
| 247 | int size = fileUrlsToLoad.size(); |
|---|
| 248 | for(int i=0; i<size; i++) { |
|---|
| 249 | MessageNode messageNode = readMessageNode((String)fileUrlsToLoad.elementAt(i)); |
|---|
| 250 | if(messageNode != null) { |
|---|
| 251 | if(loadContent) { |
|---|
| 252 | MimeMessageContent[] content = readMessageContent(mailboxNode, messageNode.getMessageToken()); |
|---|
| 253 | messageNode.putMessageContent(content); |
|---|
| 254 | } |
|---|
| 255 | callback.messageNodeUpdated(messageNode); |
|---|
| 256 | } |
|---|
| 257 | } |
|---|
| 258 | |
|---|
| 259 | callback.messageNodeUpdated(null); |
|---|
| 260 | } |
|---|
| 261 | |
|---|
| 262 | private String[] getMessageFiles(MailboxNode mailboxNode) throws IOException { |
|---|
| 263 | SimpleSortingVector fileVector = new SimpleSortingVector(); |
|---|
| 264 | if(mailSettings.getGlobalConfig().getDispOrder()) { |
|---|
| 265 | fileVector.setSortComparator(new MailFileComparator()); |
|---|
| 266 | } |
|---|
| 267 | else { |
|---|
| 268 | fileVector.setSortComparator(new InvertedOrderComparator(new MailFileComparator())); |
|---|
| 269 | } |
|---|
| 270 | fileVector.setSort(true); |
|---|
| 271 | |
|---|
| 272 | FileConnection fileConnection = getMailboxFileConnection(mailboxNode); |
|---|
| 273 | String mailboxUrl = fileConnection.getURL(); |
|---|
| 274 | Enumeration e = fileConnection.list(MSG_FILTER, false); |
|---|
| 275 | while(e.hasMoreElements()) { |
|---|
| 276 | fileVector.addElement(e.nextElement()); |
|---|
| 277 | } |
|---|
| 278 | fileConnection.close(); |
|---|
| 279 | |
|---|
| 280 | int size = fileVector.size(); |
|---|
| 281 | String[] result = new String[size]; |
|---|
| 282 | for(int i=0; i<size; i++) { |
|---|
| 283 | result[i] = mailboxUrl + fileVector.elementAt(i); |
|---|
| 284 | } |
|---|
| 285 | return result; |
|---|
| 286 | } |
|---|
| 287 | |
|---|
| 288 | public synchronized MessageNode readMessageNode(MailboxNode mailboxNode, MessageToken messageToken, boolean loadContent) throws IOException { |
|---|
| 289 | if(cacheUrl == null) { return null; } |
|---|
| 290 | |
|---|
| 291 | FileConnection fileConnection = getMailboxFileConnection(mailboxNode); |
|---|
| 292 | if(!fileConnection.exists()) { return null; } |
|---|
| 293 | |
|---|
| 294 | String mailboxUrl = fileConnection.getURL(); |
|---|
| 295 | fileConnection.close(); |
|---|
| 296 | String fileUrl = |
|---|
| 297 | mailboxUrl |
|---|
| 298 | + messageToken.getMessageUid() |
|---|
| 299 | + MSG_SUFFIX; |
|---|
| 300 | MessageNode messageNode = readMessageNode(fileUrl); |
|---|
| 301 | if(loadContent) { |
|---|
| 302 | MimeMessageContent[] content = readMessageContent(mailboxNode, messageToken); |
|---|
| 303 | messageNode.putMessageContent(content); |
|---|
| 304 | } |
|---|
| 305 | return messageNode; |
|---|
| 306 | } |
|---|
| 307 | |
|---|
| 308 | public synchronized MimeMessageContent[] readMessageContent(MailboxNode mailboxNode, MessageToken messageToken) throws IOException { |
|---|
| 309 | if(cacheUrl == null) { return null; } |
|---|
| 310 | |
|---|
| 311 | FileConnection fileConnection = getMailboxFileConnection(mailboxNode); |
|---|
| 312 | if(!fileConnection.exists()) { return null; } |
|---|
| 313 | |
|---|
| 314 | String mailboxUrl = fileConnection.getURL(); |
|---|
| 315 | fileConnection.close(); |
|---|
| 316 | String fileUrl = |
|---|
| 317 | mailboxUrl |
|---|
| 318 | + messageToken.getMessageUid() |
|---|
| 319 | + MSG_SUFFIX; |
|---|
| 320 | MimeMessageContent[] messageContent = readMessageContent(fileUrl, messageToken); |
|---|
| 321 | |
|---|
| 322 | return messageContent; |
|---|
| 323 | } |
|---|
| 324 | |
|---|
| 325 | private FileConnection getMailboxFileConnection(MailboxNode mailboxNode) throws IOException { |
|---|
| 326 | // Build the account and mailbox UID strings |
|---|
| 327 | String accountUid; |
|---|
| 328 | String mailboxUid; |
|---|
| 329 | if(mailboxNode instanceof OutboxMailboxNode) { |
|---|
| 330 | accountUid = LOCAL_ACCOUNT_UID; |
|---|
| 331 | mailboxUid = LOCAL_OUTBOX_UID; |
|---|
| 332 | } |
|---|
| 333 | else { |
|---|
| 334 | accountUid = StringParser.toHexString( |
|---|
| 335 | ((NetworkAccountNode)mailboxNode.getParentAccount()).getUniqueId()).toLowerCase(); |
|---|
| 336 | mailboxUid = StringParser.toHexString( |
|---|
| 337 | mailboxNode.getUniqueId()).toLowerCase(); |
|---|
| 338 | } |
|---|
| 339 | |
|---|
| 340 | StringBuffer buf = new StringBuffer(cacheUrl); |
|---|
| 341 | |
|---|
| 342 | // Open the account directory, creating if necessary |
|---|
| 343 | buf.append(accountUid); buf.append('/'); |
|---|
| 344 | FileConnection fileConnection = (FileConnection)Connector.open(buf.toString()); |
|---|
| 345 | if(!fileConnection.exists()) { |
|---|
| 346 | fileConnection.mkdir(); |
|---|
| 347 | } |
|---|
| 348 | fileConnection.close(); |
|---|
| 349 | |
|---|
| 350 | // Traverse to the mailbox directory, creating if necessary |
|---|
| 351 | buf.append(mailboxUid); buf.append('/'); |
|---|
| 352 | fileConnection = (FileConnection)Connector.open(buf.toString()); |
|---|
| 353 | if(!fileConnection.exists()) { |
|---|
| 354 | fileConnection.mkdir(); |
|---|
| 355 | } |
|---|
| 356 | |
|---|
| 357 | return fileConnection; |
|---|
| 358 | } |
|---|
| 359 | |
|---|
| 360 | private MessageToken readMessageToken(String fileUrl) { |
|---|
| 361 | MessageToken result; |
|---|
| 362 | FileConnection fileConnection = null; |
|---|
| 363 | try { |
|---|
| 364 | fileConnection = (FileConnection)Connector.open(fileUrl); |
|---|
| 365 | DataInputStream input = fileConnection.openDataInputStream(); |
|---|
| 366 | MessageNodeReader reader = new MessageNodeReader(input); |
|---|
| 367 | result = reader.read(); |
|---|
| 368 | input.close(); |
|---|
| 369 | fileConnection.close(); |
|---|
| 370 | } catch (Exception e) { |
|---|
| 371 | EventLogger.logEvent(AppInfo.GUID, |
|---|
| 372 | ("Unable to read token: " + fileUrl |
|---|
| 373 | + "\r\n" + e.getMessage()).getBytes(), |
|---|
| 374 | EventLogger.ERROR); |
|---|
| 375 | result = null; |
|---|
| 376 | } finally { |
|---|
| 377 | if(fileConnection != null) { |
|---|
| 378 | try { fileConnection.close(); } catch (Exception e) { } |
|---|
| 379 | } |
|---|
| 380 | } |
|---|
| 381 | return result; |
|---|
| 382 | } |
|---|
| 383 | |
|---|
| 384 | private MessageNode readMessageNode(String fileUrl) { |
|---|
| 385 | MessageNode result; |
|---|
| 386 | FileConnection fileConnection = null; |
|---|
| 387 | try { |
|---|
| 388 | fileConnection = (FileConnection)Connector.open(fileUrl); |
|---|
| 389 | DataInputStream input = fileConnection.openDataInputStream(); |
|---|
| 390 | MessageNodeReader reader = new MessageNodeReader(input); |
|---|
| 391 | result = reader.readMessageNode(); |
|---|
| 392 | result.setCached(true); |
|---|
| 393 | input.close(); |
|---|
| 394 | fileConnection.close(); |
|---|
| 395 | } catch (Exception e) { |
|---|
| 396 | EventLogger.logEvent(AppInfo.GUID, |
|---|
| 397 | ("Unable to read token: " + fileUrl |
|---|
| 398 | + "\r\n" + e.getMessage()).getBytes(), |
|---|
| 399 | EventLogger.ERROR); |
|---|
| 400 | result = null; |
|---|
| 401 | } finally { |
|---|
| 402 | if(fileConnection != null) { |
|---|
| 403 | try { fileConnection.close(); } catch (Exception e) { } |
|---|
| 404 | } |
|---|
| 405 | } |
|---|
| 406 | return result; |
|---|
| 407 | } |
|---|
| 408 | |
|---|
| 409 | private MimeMessageContent[] readMessageContent(String fileUrl, MessageToken messageToken) { |
|---|
| 410 | FileConnection fileConnection = null; |
|---|
| 411 | Vector content = new Vector(); |
|---|
| 412 | try { |
|---|
| 413 | fileConnection = (FileConnection)Connector.open(fileUrl); |
|---|
| 414 | DataInputStream input = fileConnection.openDataInputStream(); |
|---|
| 415 | MessageNodeReader reader = new MessageNodeReader(input); |
|---|
| 416 | MessageToken tempToken = reader.read(); |
|---|
| 417 | if(messageToken.equals(tempToken)) { |
|---|
| 418 | while(reader.isContentAvailable()) { |
|---|
| 419 | content.addElement(reader.getNextContent()); |
|---|
| 420 | } |
|---|
| 421 | } |
|---|
| 422 | input.close(); |
|---|
| 423 | fileConnection.close(); |
|---|
| 424 | } catch (Exception e) { |
|---|
| 425 | EventLogger.logEvent(AppInfo.GUID, |
|---|
| 426 | ("Unable to read content: " + fileUrl |
|---|
| 427 | + "\r\n" + e.getMessage()).getBytes(), |
|---|
| 428 | EventLogger.ERROR); |
|---|
| 429 | } finally { |
|---|
| 430 | if(fileConnection != null) { |
|---|
| 431 | try { fileConnection.close(); } catch (Exception e) { } |
|---|
| 432 | } |
|---|
| 433 | } |
|---|
| 434 | MimeMessageContent[] result = new MimeMessageContent[content.size()]; |
|---|
| 435 | content.copyInto(result); |
|---|
| 436 | return result; |
|---|
| 437 | } |
|---|
| 438 | |
|---|
| 439 | public synchronized void removeStaleMessageNodes(MailboxNode mailboxNode, String[] uidsToRetain) throws IOException { |
|---|
| 440 | if(cacheUrl == null) { return; } |
|---|
| 441 | |
|---|
| 442 | Hashtable retentionSet = new Hashtable(); |
|---|
| 443 | for(int i=0; i<uidsToRetain.length; i++) { |
|---|
| 444 | retentionSet.put(uidsToRetain[i], Boolean.TRUE); |
|---|
| 445 | } |
|---|
| 446 | |
|---|
| 447 | String[] fileUrls = getMessageFiles(mailboxNode); |
|---|
| 448 | Vector fileUrlsToDelete = new Vector(); |
|---|
| 449 | for(int i=0; i<fileUrls.length; i++) { |
|---|
| 450 | int p = fileUrls[i].lastIndexOf('/'); |
|---|
| 451 | int q = fileUrls[i].lastIndexOf('.'); |
|---|
| 452 | if(p != -1 && q != -1 && p < q) { |
|---|
| 453 | String messageUid = fileUrls[i].substring(p + 1, q); |
|---|
| 454 | if(!retentionSet.containsKey(messageUid)) { |
|---|
| 455 | fileUrlsToDelete.addElement(fileUrls[i]); |
|---|
| 456 | } |
|---|
| 457 | } |
|---|
| 458 | } |
|---|
| 459 | |
|---|
| 460 | int size = fileUrlsToDelete.size(); |
|---|
| 461 | for(int i=0; i<size; i++) { |
|---|
| 462 | try { |
|---|
| 463 | FileConnection fc = (FileConnection)Connector.open((String)fileUrlsToDelete.elementAt(i)); |
|---|
| 464 | if(fc.exists() && fc.canRead()) { |
|---|
| 465 | fc.delete(); |
|---|
| 466 | } |
|---|
| 467 | } catch (IOException exp) { |
|---|
| 468 | if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { |
|---|
| 469 | EventLogger.logEvent(AppInfo.GUID, |
|---|
| 470 | ("Error deleting message from cache: " + exp.toString()).getBytes(), |
|---|
| 471 | EventLogger.DEBUG_INFO); |
|---|
| 472 | } |
|---|
| 473 | } |
|---|
| 474 | } |
|---|
| 475 | } |
|---|
| 476 | |
|---|
| 477 | public synchronized void removeMessageNodes(MailboxNode mailboxNode, MessageToken[] messageTokens) throws IOException { |
|---|
| 478 | if(cacheUrl == null) { return; } |
|---|
| 479 | |
|---|
| 480 | FileConnection fileConnection = getMailboxFileConnection(mailboxNode); |
|---|
| 481 | String mailboxUrl = fileConnection.getURL(); |
|---|
| 482 | fileConnection.close(); |
|---|
| 483 | |
|---|
| 484 | for(int i=0; i<messageTokens.length; i++) { |
|---|
| 485 | try { |
|---|
| 486 | FileConnection mailFileConnection = |
|---|
| 487 | (FileConnection)Connector.open(mailboxUrl + messageTokens[i].getMessageUid() + MSG_SUFFIX); |
|---|
| 488 | if(mailFileConnection.exists() && !mailFileConnection.isDirectory() && mailFileConnection.canRead()) { |
|---|
| 489 | mailFileConnection.delete(); |
|---|
| 490 | } |
|---|
| 491 | mailFileConnection.close(); |
|---|
| 492 | } catch (IOException exp) { |
|---|
| 493 | if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { |
|---|
| 494 | EventLogger.logEvent(AppInfo.GUID, |
|---|
| 495 | ("Error deleting message from cache: " + exp.toString()).getBytes(), |
|---|
| 496 | EventLogger.DEBUG_INFO); |
|---|
| 497 | } |
|---|
| 498 | } |
|---|
| 499 | } |
|---|
| 500 | } |
|---|
| 501 | |
|---|
| 502 | public synchronized void removeMessageNode(MailboxNode mailboxNode, MessageToken messageToken) throws IOException { |
|---|
| 503 | if(cacheUrl == null) { return; } |
|---|
| 504 | |
|---|
| 505 | FileConnection fileConnection = getMailboxFileConnection(mailboxNode); |
|---|
| 506 | String mailboxUrl = fileConnection.getURL(); |
|---|
| 507 | fileConnection.close(); |
|---|
| 508 | |
|---|
| 509 | try { |
|---|
| 510 | FileConnection mailFileConnection = |
|---|
| 511 | (FileConnection)Connector.open(mailboxUrl + messageToken.getMessageUid() + MSG_SUFFIX); |
|---|
| 512 | if(mailFileConnection.exists() && !mailFileConnection.isDirectory() && mailFileConnection.canRead()) { |
|---|
| 513 | mailFileConnection.delete(); |
|---|
| 514 | } |
|---|
| 515 | mailFileConnection.close(); |
|---|
| 516 | } catch (IOException exp) { |
|---|
| 517 | if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { |
|---|
| 518 | EventLogger.logEvent(AppInfo.GUID, |
|---|
| 519 | ("Error deleting message from cache: " + exp.toString()).getBytes(), |
|---|
| 520 | EventLogger.DEBUG_INFO); |
|---|
| 521 | } |
|---|
| 522 | } |
|---|
| 523 | } |
|---|
| 524 | } |
|---|