source: trunk/LogicMail/src/org/logicprobe/LogicMail/mail/NetworkMailStore.java @ 964

Revision 964, 12.1 KB checked in by octorian, 5 months ago (diff)

Added experimental WiFi connection handover support (refs #79)

Line 
1/*-
2 * Copyright (c) 2008, 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
32package org.logicprobe.LogicMail.mail;
33
34import java.util.Date;
35
36import net.rim.device.api.system.UnsupportedOperationException;
37
38import org.logicprobe.LogicMail.conf.AccountConfig;
39import org.logicprobe.LogicMail.mail.imap.ImapClient;
40import org.logicprobe.LogicMail.mail.pop.PopClient;
41import org.logicprobe.LogicMail.message.FolderMessage;
42import org.logicprobe.LogicMail.message.MessageFlags;
43import org.logicprobe.LogicMail.message.MimeMessagePart;
44
45public class NetworkMailStore extends AbstractMailStore {
46        private IncomingMailClient client;
47        private IncomingMailConnectionHandler connectionHandler;
48        private AccountConfig accountConfig;
49        public NetworkMailStore(AccountConfig accountConfig) {
50                super();
51                this.client = MailClientFactory.createMailClient(accountConfig);
52                this.accountConfig = accountConfig;
53                this.connectionHandler = new IncomingMailConnectionHandler(this, client);
54                this.connectionHandler.start();
55        }
56
57    /**
58         * Gets the account configuration associated with this network mail store.
59         *
60         * @return Account configuration.
61         */
62        public AccountConfig getAccountConfig() {
63                return this.accountConfig;
64        }
65       
66        public void shutdown(boolean wait) {
67                connectionHandler.shutdown(wait);
68        }
69
70        /**
71         * Restarts the mail connection handler thread.
72         */
73        public void restart() {
74                if(!connectionHandler.isRunning()) {
75                        connectionHandler.start();
76                }
77        }
78       
79        public boolean isLocal() {
80                return false;
81        }
82
83        public boolean hasFolders() {
84                return client.hasFolders();
85        }
86
87        public boolean hasMessageParts() {
88                return client.hasMessageParts();
89        }
90       
91        public boolean hasFlags() {
92                return client.hasFlags();
93        }
94       
95        public boolean hasAppend() {
96                return client.hasAppend();
97        }
98
99        public boolean hasCopy() {
100                return client.hasCopy();
101        }
102       
103        public boolean hasUndelete() {
104                return client.hasUndelete();
105        }
106
107        public boolean hasExpunge() {
108            return client.hasExpunge();
109        }
110       
111        /**
112         * Returns whether the mail store supports retrieval of a full folder
113         * message index-to-UID map.
114         *
115         * @return True if index-to-UID map retrieval is supported, false otherwise
116         * @see #requestFolderMessageIndexMap(FolderTreeItem, MailStoreRequestCallback)
117         */
118        public boolean hasFolderMessageIndexMap() {
119            return client.hasFolderMessageIndexMap();
120        }
121       
122        /**
123         * Returns whether the mail store has a locked folder view while connected.
124         * If this method returns true, then an explicit refresh during an existing
125         * connection will not return new data.
126         * @return True if folder contents are locked while connected, false otherwise.
127         */
128        public boolean hasLockedFolders() {
129            return client.hasLockedFolders();
130        }
131       
132        public boolean isConnected() {
133                return client.isConnected();
134        }
135
136        /**
137         * Gets the inbox folder, if available.
138         */
139        public FolderTreeItem getInboxFolder() {
140            return client.getInboxFolder();
141        }
142       
143    /**
144     * Requests that the mail store disconnect from the mail server.
145     * <p>
146     * Unlike the <code>shutdown(boolean)</code> method, this does not cause
147     * the connection handler thread to terminate.  As such, any subsequent
148     * request may cause it to reconnect.
149     * </p>
150     */
151    public void requestDisconnect() {
152        processRequest(new NetworkDisconnectRequest(this, NetworkDisconnectRequest.REQUEST_DISCONNECT));
153    }
154
155    /**
156     * Creates a request to instruct the connection handler thread to start
157     * its polling timer, if the connection is closed and it is not already
158     * started.
159     */
160    public NetworkPollingStartRequest createPollingStartRequest() {
161        NetworkPollingStartRequest request = new NetworkPollingStartRequest(this);
162        return request;
163    }
164
165    /**
166     * Creates a request to instruct the mail client to enable or disable its
167     * idle mode.  This request is useful at the beginning and end of a batch
168     * operation, to prevent the mail client from entering and exiting idle
169     * mode between requests.
170     *
171     * @param idleEnabled whether or not the idle mode should be enabled
172     */
173    public NetworkClientIdleModeRequest createClientIdleModeRequest(boolean idleEnabled) {
174        NetworkClientIdleModeRequest request = new NetworkClientIdleModeRequest(this, idleEnabled);
175        return request;
176    }
177   
178        public FolderTreeRequest createFolderTreeRequest() {
179            NetworkFolderTreeRequest request = new NetworkFolderTreeRequest(this);
180                return request;
181        }
182
183        public FolderExpungeRequest createFolderExpungeRequest(FolderTreeItem folder) {
184            NetworkFolderExpungeRequest request = new NetworkFolderExpungeRequest(this, folder);
185        return request;
186        }
187       
188        public FolderStatusRequest createFolderStatusRequest(FolderTreeItem[] folders) {
189            NetworkFolderStatusRequest request = new NetworkFolderStatusRequest(this, folders);
190        return request;
191        }
192
193        public FolderMessagesRequest createFolderMessagesRangeRequest(FolderTreeItem folder, MessageToken firstToken, int increment) {
194            if(firstToken == null || increment <= 0) {
195                throw new IllegalArgumentException();
196            }
197               
198            NetworkFolderMessagesRequest request = new NetworkFolderMessagesRequest(this, folder, firstToken, increment);
199            return request;
200        }
201
202        public FolderMessagesRequest createFolderMessagesSetRequest(FolderTreeItem folder, MessageToken[] messageTokens, boolean flagsOnly) {
203        NetworkFolderMessagesRequest request = new NetworkFolderMessagesRequest(this, folder, messageTokens, flagsOnly);
204        return request;
205        }
206       
207        public FolderMessagesRequest createFolderMessagesSetByIndexRequest(FolderTreeItem folder, int[] messageIndices) {
208        NetworkFolderMessagesRequest request = new NetworkFolderMessagesRequest(this, folder, messageIndices);
209        return request;
210        }
211       
212        public FolderMessagesRequest createFolderMessagesRecentRequest(FolderTreeItem folder, boolean flagsOnly) {
213        NetworkFolderMessagesRequest request = new NetworkFolderMessagesRequest(this, folder, flagsOnly);
214        return request;
215        }
216       
217        /**
218         * Creates a request to synchronize a locally cached folder with data from
219         * the mail server.  This is a complex request with protocol-dependent
220         * implementations, and is intended to be called from within cache-handling
221         * code.
222         *
223         * @param folder The folder to refresh.
224         * @param loadedMessages Collection of {@link FolderMessage} objects
225         *     for messages that have already been loaded for this folder prior to
226         *     the start of the refresh operation.
227         * @return the request object
228         */
229        public MailStoreRequest createFolderRefreshRequest(FolderTreeItem folder, FolderMessage[] loadedMessages) {
230            if(client instanceof ImapClient) {
231            return new ImapFolderRefreshRequest(this, folder, loadedMessages);
232            }
233            else if(client instanceof PopClient) {
234                return new PopFolderRefreshRequest(this, folder, loadedMessages);
235            }
236            else {
237                throw new UnsupportedOperationException();
238            }
239        }
240       
241        public MessageRequest createMessageRequest(MessageToken messageToken, boolean useLimits) {
242                NetworkMessageRequest request = new NetworkMessageRequest(this, messageToken, useLimits);
243        return request;
244        }
245
246        public MessageRequest createMessagePartsRequest(MessageToken messageToken, MimeMessagePart[] messageParts) {
247                NetworkMessageRequest request = new NetworkMessageRequest(this, messageToken, messageParts);
248        return request;
249        }
250       
251        public MessageFlagChangeRequest createMessageFlagChangeRequest(
252                MessageToken messageToken,
253                MessageFlags messageFlags,
254                boolean addOrRemove) {
255
256            if(messageFlags.isDeleted()) {
257                if(!addOrRemove && !client.hasUndelete()) {
258                    throw new UnsupportedOperationException();
259                }
260            }
261            else if(!this.hasFlags()) {
262                throw new UnsupportedOperationException();
263            }
264
265            NetworkMessageFlagChangeRequest request = new NetworkMessageFlagChangeRequest(this, messageToken, messageFlags, addOrRemove);
266            return request;
267        }
268       
269    public MessageFlagChangeRequest createMessageFlagChangeRequest(
270            MessageToken[] messageTokens,
271            MessageFlags messageFlags,
272            boolean addOrRemove) {
273
274        if(messageFlags.isDeleted()) {
275            if(!addOrRemove && !client.hasUndelete()) {
276                throw new UnsupportedOperationException();
277            }
278        }
279        else if(!this.hasFlags()) {
280            throw new UnsupportedOperationException();
281        }
282
283        NetworkMessageFlagChangeRequest request = new NetworkMessageFlagChangeRequest(this, messageTokens, messageFlags, addOrRemove);
284        return request;
285    }
286       
287        public MessageRangeFlagChangeRequest createMessageRangeFlagChangeRequest(
288                FolderTreeItem folder,
289                Date startDate,
290                MessageFlags messageFlags,
291                boolean addOrRemove) {
292
293            throw new UnsupportedOperationException();
294        }
295   
296        public MessageAppendRequest createMessageAppendRequest(FolderTreeItem folder, String rawMessage, MessageFlags initialFlags) {
297                if(!this.hasAppend()) {
298                        throw new UnsupportedOperationException();
299                }
300                NetworkMessageAppendRequest request = new NetworkMessageAppendRequest(this, folder, rawMessage, initialFlags);
301                return request;
302        }
303       
304        public MessageCopyRequest createMessageCopyRequest(MessageToken messageToken, FolderTreeItem destinationFolder) {
305            if(!this.hasCopy()) {
306                throw new UnsupportedOperationException();
307            }
308            NetworkMessageCopyRequest request = new NetworkMessageCopyRequest(this, messageToken, destinationFolder);
309            return request;
310        }
311       
312    public void processRequest(MailStoreRequest request) {
313        if(request instanceof NetworkMailStoreRequest
314                && request instanceof ConnectionHandlerRequest) {
315            connectionHandler.addRequest((ConnectionHandlerRequest)request);
316        }
317        else {
318            throw new IllegalArgumentException();
319        }
320    }
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   
338    IncomingMailConnectionHandler getConnectionHandler() {
339        return connectionHandler;
340    }
341}
Note: See TracBrowser for help on using the repository browser.