⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mailsyncsource.java

📁 The Funambol J2ME Mail Client aims to be a light, easy to use, free email client for J2ME devices.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -