📄 mailsyncsource.java
字号:
/*
* Copyright (C) 2006-2007 Funambol
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.funambol.mailclient.syncml;
import com.funambol.mailclient.mm.MessageManager;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Date;
import com.funambol.mailclient.AccountListener;
import com.funambol.syncml.client.BaseSyncSource;
import com.funambol.syncml.protocol.SyncML;
import com.funambol.syncml.protocol.SyncMLStatus;
import com.funambol.syncml.spds.SourceConfig;
import com.funambol.syncml.spds.SyncItem;
import com.funambol.syncml.spds.SyncException;
import com.funambol.mail.Folder;
import com.funambol.mail.Message;
import com.funambol.mail.MessageFlags;
import com.funambol.mail.Store;
import com.funambol.mail.StoreFactory;
import com.funambol.mail.MailException;
import com.funambol.util.Log;
import com.funambol.util.XmlException;
/**
* An implementation of the <i>SyncSource</i> interface, used to send
* and receive email over the SyncML protocol.
*
*/
public class MailSyncSource extends BaseSyncSource {
public static final String FOLDER_TYPE = "application/vnd.omads-folder+xml";
public static final String EMAIL_TYPE = "application/vnd.omads-email+xml";
//--------------------------------------------------------------- Attributes
/** Reference to the mail store */
private Store store;
/** Reference to the account listener */
private AccountListener listener;
/** A global status code for the MailSyncSource */
private int mailSourceStatus;
/** Flag used to mark the beginning of the receiving phase */
private boolean receiving;
//------------------------------------------------------------- Constructors
/**
* MailSyncSource constructor: initialize source config and
* init all the rest to null. The real initialization is done by
* the beginSync method.
*/
public MailSyncSource(SourceConfig config) {
super(config);
store = StoreFactory.getStore();
listener = null;
mailSourceStatus = AccountListener.STATUS_SUCCESS;
receiving = false;
}
//----------------------------------------------------------- Public Methods
/**
* Set an AccountListener for this Mail source.
*/
public void setListener(AccountListener listener) {
this.listener = listener;
}
/**
* Called after SyncManager preparation and initialization just before start
* the synchronization of the SyncSource.
*
* @param syncMode the synchronization type: one of the values in
* sync4j.framework.core.AlertCode
*
* @throws SyncException in case of error. This will stop the sync process
*/
public void beginSync(int syncMode) throws SyncException {
super.beginSync(syncMode); // call BaseSyncSource.beginSync()
int action = AccountListener.ACTION_NONE;
if(syncMode == SyncML.ALERT_CODE_REFRESH_FROM_SERVER ||
syncMode == SyncML.ALERT_CODE_SLOW) {
// Remove local mail in INBOX
try {
store.removeFolder(store.INBOX);
store.createFolder(store.INBOX);
// we need to reset the inbox but we don't want the user
// to catch us performing in a slow sync required
// from the server... so we refresh the inbox
// only when we are doing a refresh from server (that
// has probably been requested by our client)
if ( syncMode == SyncML.ALERT_CODE_REFRESH_FROM_SERVER ) {
action = AccountListener.ACTION_RESET_INBOX;
}
} catch(MailException se) {
Log.error("[MailSyncSource.beginSync]:"+se.toString());
throw new SyncException(
SyncException.CLIENT_ERROR,
"Error cleaning local mail: " +se.toString());
}
}
mailSourceStatus = AccountListener.STATUS_SUCCESS;
receiving = false;
if(listener != null) {
listener.connectionCompleted(action);
}
}
/**
* Called just before committing the synchronization process by the
* SyncManager. The SyncSource can stop the commit phase raising an
* exception here.
*
* @throws SyncException in case of error, to stop the commit.
*/
public void endSync() throws SyncException {
super.endSync(); // call BaseSyncSource.endSync()
if(listener != null) {
listener.endSession(mailSourceStatus);
}
}
/**
* Add a new item from the server to the mail store.
*/
public int addItem(SyncItem item) throws SyncException {
Log.info("New item " + item.getKey() + " from server.");
if(item.getType().equals(EMAIL_TYPE)) {
// Parse the mail item
Log.debug("Email item");
return handleEmailItem(item);
} else if(item.getType().equals(FOLDER_TYPE)) {
// Parse the mail item
Log.debug("Folder item");
return addFolderItem(item);
} else {
Log.error("[MailSyncSource.addItem] Unknown item type: "
+ item.getType());
return 500;
}
}
/** Update a given SyncItem stored on the source backend */
public int updateItem(SyncItem item) throws SyncException {
Log.info("Updated item " + item.getKey() + " from server.");
if(item.getType().equals(EMAIL_TYPE)) {
// Parse the mail item
Log.debug("Email item");
return handleEmailItem(item);
} else if(item.getType().equals(FOLDER_TYPE)) {
// Parse the mail item
Log.debug("Folder item update: ignored");
return 200;
} else {
Log.info("[MailSyncSource.updateItem] Unexpected item type"
+ item.getType());
return 500;
}
}
/** Delete a SyncItem stored on the related Items list */
public int deleteItem(String key) throws SyncException {
Log.info("Delete from server for item " + key);
try {
Log.debug("[deleteItem]Email item");
String parent = folderFromKey(key);
if(parent == null){
Log.error("Invalid key from server: " +key);
return 500;
}
Folder f = store.getFolder(parent);
String msgId = msgIdFromKey(key);
f.deleteMessage(msgId);
if(listener != null) {
listener.msgDeleted(msgId);
}
return 200;
} catch (MailException me) {
Log.error("Error removing message: " + key
+ " " + me.toString() );
mailSourceStatus = AccountListener.STATUS_RECV_ERROR;
return 500;
}
}
/**
* Tell the SyncSource the status returned by the server
* for an Item previously sent.
*
* @param key the key of the item
* @param status the status code received for that item
*
* @throws SyncException if the SyncSource wants to stop the sync
*/
public void setItemStatus(String key, int status)
throws SyncException {
Log.info("Status " + status + " for item " + key + " from server.");
try {
String folder = folderFromKey(key);
String msgId = msgIdFromKey(key);
if(Store.OUTBOX.equals(folder)) {
if (SyncMLStatus.isSuccess(status)) {
// Move the message in the sent folder
Folder sent = store.getFolder(Store.SENT);
Folder outbox = store.getFolder(Store.OUTBOX);
Message msg = outbox.getMessage(msgId);
msg.getFlags().setFlag(MessageFlags.TX_SENDING, false);
msg.getFlags().setFlag(MessageFlags.TX_SENT, true);
sent.appendMessage(msg);
outbox.deleteMessage(msg);
if(listener != null) {
listener.msgSent();
}
} else {
mailSourceStatus = AccountListener.STATUS_SEND_ERROR;
// TODO: send an event to the client?
}
}
if (Store.INBOX.equals(folder)) {
MessageFlags newMask = FlagQueue.get(key);
if (newMask!=null
&&(newMask.isSet(MessageFlags.ANSWERED)
||newMask.isSet(MessageFlags.FORWARDED))) {
Folder inbox = store.getFolder(Store.INBOX);
Message msg = inbox.getMessage(msgId);
msg.setFlags(newMask);
inbox.appendMessage(msg);
listener.msgFlagsUpdated(msg.getMessageId(), msg.getFlags());
}
}
FlagQueue.remove(key);
} catch (MailException me) {
me.printStackTrace();
Log.error("setItemStatus: error setting the status for item:"+key);
}
}
/**
* Extends BaseSyncSource.getNextItem() to send events
*/
public SyncItem getNextItem() throws SyncException {
SyncItem ret = super.getNextItem();
// If it's the last item, send the endSending() to the listener
if(ret == null && listener != null) {
listener.endSending();
}
return ret;
}
/**
* Extends BaseSyncSource.getNextNewItem() to send events
*/
public SyncItem getNextNewItem() throws SyncException {
SyncItem ret = super.getNextNewItem();
// If it's the last item, send the endSending() to the listener
if(ret == null && listener != null) {
listener.endSending();
}
return ret;
}
/**
* Extends BaseSyncSource.dataReceived() to send events
*/
public void dataReceived(String date, int size) {
if(date != null && listener != null) {
listener.dataReceived(date, size);
}
}
/**
* Send incomingMsgNumber event when the engine announce the number of
* changes: it is the first Sync tag from server.
*/
public void setServerItemsNumber(int number) {
super.setServerItemsNumber(number);
if (!receiving && listener != null) {
listener.startReceiving(number);
}
receiving = true;
}
//------------------------------------------------------- Protected methods
/**
* Init the allItems list used in the slow sync with the messages
* in the outbox only.
*/
protected void initAllItems() throws SyncException {
if (listener != null) {
listener.startSending(0);
}
/*
FIXME: check with the server why the folders are not accepted.
allItems = new SyncItem[2];
FolderData inbox = new FolderData("Inbox", new Date(), "inbox");
FolderData outbox = new FolderData("Outbox", new Date(), "outbox");
allItems[0] = new SyncItem ("Inbox",
FOLDER_TYPE,
SyncItem.STATE_UPDATED,
"/",
inbox.format());
allItems[1] = new SyncItem ("Outbox",
FOLDER_TYPE,
SyncItem.STATE_UPDATED,
"/",
outbox.format());
*/
/*
try {
// Get the keys of the messages in the Outbox only.
Folder outbox = store.getFolder(Store.OUTBOX);
Message[] headers = outbox.getMsgHeaders();
int count = headers.length;
if (count > 0) {
allItems = new SyncItem[count];
for(int i=0; i<count; i++) {
allItems[i] = new SyncItem(headers[i].getMessageId());
allItems[i].setParent(Store.OUTBOX);
allItems[i].setState(SyncItem.STATE_UPDATED);
}
}
else {
allItems = null;
}
}
catch (MailException me) {
Log.error("[MailSyncSource.initAllItems]: " + me.toString());
throw new SyncException(me.toString());
}
*/
}
/**
* Init the newItems list used in the fast sync with the messages
* in the outbox only.
* TODO: check the state of the message
*/
protected void initNewItems() throws SyncException {
try {
// Get the keys of the messages in the Outbox only.
Folder outbox = store.getFolder(Store.OUTBOX);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -