FolderSyncParser.java revision 00d91b2e12d65df06916afdc4bebca67fd27214c
1ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank/* 2ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Copyright (C) 2008-2009 Marc Blank 3ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Licensed to The Android Open Source Project. 4ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * 5ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Licensed under the Apache License, Version 2.0 (the "License"); 6ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * you may not use this file except in compliance with the License. 7ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * You may obtain a copy of the License at 8ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * 9ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * http://www.apache.org/licenses/LICENSE-2.0 10ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * 11ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Unless required by applicable law or agreed to in writing, software 12ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * distributed under the License is distributed on an "AS IS" BASIS, 13ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * See the License for the specific language governing permissions and 15ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * limitations under the License. 16ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank */ 17ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 18ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankpackage com.android.exchange.adapter; 19ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 20ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport com.android.email.provider.EmailProvider; 21ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport com.android.exchange.Eas; 22ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport com.android.exchange.EasSyncService; 23ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport com.android.exchange.MockParserStream; 24ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport com.android.exchange.SyncManager; 25ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport com.android.exchange.EmailContent.Account; 26ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport com.android.exchange.EmailContent.Mailbox; 27ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport com.android.exchange.EmailContent.MailboxColumns; 28ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 29ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.content.ContentProviderOperation; 30ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.content.ContentResolver; 31ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.content.ContentUris; 32ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.content.Context; 33ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.content.OperationApplicationException; 34ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.database.Cursor; 35ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.os.RemoteException; 36ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.util.Log; 37ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 3800d91b2e12d65df06916afdc4bebca67fd27214cMarc Blankimport java.io.IOException; 3900d91b2e12d65df06916afdc4bebca67fd27214cMarc Blankimport java.io.InputStream; 4000d91b2e12d65df06916afdc4bebca67fd27214cMarc Blankimport java.util.ArrayList; 4100d91b2e12d65df06916afdc4bebca67fd27214cMarc Blankimport java.util.Arrays; 4200d91b2e12d65df06916afdc4bebca67fd27214cMarc Blankimport java.util.List; 4300d91b2e12d65df06916afdc4bebca67fd27214cMarc Blank 44ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank/** 45ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Parse the result of a FolderSync command 46ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * 47ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Handles the addition, deletion, and changes to folders in the user's Exchange account. 48ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank **/ 49ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 50ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankpublic class EasFolderSyncParser extends EasParser { 51ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 5222bc4e0e4f4a5e43e4eea8d59e1961860c507594Marc Blank private static boolean DEBUG_LOGGING = false; 5322bc4e0e4f4a5e43e4eea8d59e1961860c507594Marc Blank 54ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final String TAG = "FolderSyncParser"; 55ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 56ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // These are defined by the EAS protocol 57ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final int USER_FOLDER_TYPE = 1; 58ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final int INBOX_TYPE = 2; 59ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final int DRAFTS_TYPE = 3; 60ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final int DELETED_TYPE = 4; 61ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final int SENT_TYPE = 5; 62ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final int OUTBOX_TYPE = 6; 63ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final int TASKS_TYPE = 7; 64ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final int CALENDAR_TYPE = 8; 65ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final int CONTACTS_TYPE = 9; 66ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final int NOTES_TYPE = 10; 67ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final int JOURNAL_TYPE = 11; 68ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final int USER_MAILBOX_TYPE = 12; 69ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 70ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public static final List<Integer> mValidFolderTypes = Arrays.asList(INBOX_TYPE, DRAFTS_TYPE, 71ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank DELETED_TYPE, SENT_TYPE, OUTBOX_TYPE, USER_MAILBOX_TYPE, CALENDAR_TYPE, CONTACTS_TYPE); 72ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 73ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private static final String WHERE_SERVER_ID_AND_ACCOUNT = MailboxColumns.SERVER_ID + "=? and " + 74ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank MailboxColumns.ACCOUNT_KEY + "=?"; 75ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 76ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private static final String WHERE_DISPLAY_NAME_AND_ACCOUNT = MailboxColumns.DISPLAY_NAME + 77ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank "=? and " + MailboxColumns.ACCOUNT_KEY + "=?"; 78ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 79ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private static final String WHERE_PARENT_SERVER_ID_AND_ACCOUNT = 80ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank MailboxColumns.PARENT_SERVER_ID +"=? and " + MailboxColumns.ACCOUNT_KEY + "=?"; 81ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 82ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private static final String[] MAILBOX_ID_COLUMNS_PROJECTION = 83ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank new String[] {MailboxColumns.ID, MailboxColumns.SERVER_ID}; 84ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 85ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private Account mAccount; 86ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 87ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private long mAccountId; 88ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 89ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private String mAccountIdAsString; 90ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 91ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private EasSyncService mService; 92ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 93ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private Context mContext; 94ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 95ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private ContentResolver mContentResolver; 96ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 97ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private MockParserStream mMock = null; 98ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 99ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private String[] mBindArguments = new String[2]; 100ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 101ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public EasFolderSyncParser(InputStream in, EasSyncService service) throws IOException { 102ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank super(in); 103ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mService = service; 104ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mAccount = service.mAccount; 105ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mAccountId = mAccount.mId; 106ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mAccountIdAsString = Long.toString(mAccountId); 107ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mContext = service.mContext; 108ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mContentResolver = mContext.getContentResolver(); 109ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (in instanceof MockParserStream) { 110ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mMock = (MockParserStream)in; 111ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 11222bc4e0e4f4a5e43e4eea8d59e1961860c507594Marc Blank if (DEBUG_LOGGING) { 11322bc4e0e4f4a5e43e4eea8d59e1961860c507594Marc Blank setDebug(true); 11422bc4e0e4f4a5e43e4eea8d59e1961860c507594Marc Blank } 115ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 116ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 117ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public boolean parse() throws IOException { 118ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank int status; 119ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank boolean res = false; 120ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (nextTag(START_DOCUMENT) != EasTags.FOLDER_FOLDER_SYNC) 121ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank throw new IOException(); 122ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank while (nextTag(START_DOCUMENT) != END_DOCUMENT) { 123ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (tag == EasTags.FOLDER_STATUS) { 124ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank status = getValueInt(); 125ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (status != Eas.FOLDER_STATUS_OK) { 126ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mService.errorLog("FolderSync failed: " + status); 127ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (status == Eas.FOLDER_STATUS_INVALID_KEY) { 128ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mAccount.mSyncKey = "0"; 129ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mService.errorLog("Bad sync key; RESET and delete all folders"); 130ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mContentResolver.delete(Mailbox.CONTENT_URI, 131ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank MailboxColumns.ACCOUNT_KEY + '=' + mAccountId, null); 132ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // Stop existing syncs and reconstruct _main 133ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank SyncManager.folderListReloaded(mAccountId); 134ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank res = true; 135ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } else { 136ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // Other errors are at the server, so let's throw an error that will 137ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // cause this sync to be retried at a later time 138ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mService.errorLog("Throwing IOException; will retry later"); 139ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank throw new IOException(); 140ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 141ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 142ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } else if (tag == EasTags.FOLDER_SYNC_KEY) { 143ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mAccount.mSyncKey = getValue(); 144ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mService.userLog("New Account SyncKey: " + mAccount.mSyncKey); 145ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } else if (tag == EasTags.FOLDER_CHANGES) { 146ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank changesParser(); 147ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } else 148ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank skipTag(); 149ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 150ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 151ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mAccount.saveOrUpdate(mContext); 152ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank return res; 153ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 154ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 155ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank private Cursor getServerIdCursor(String serverId) { 156ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mBindArguments[0] = serverId; 157ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mBindArguments[1] = mAccountIdAsString; 158ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank return mContentResolver.query(Mailbox.CONTENT_URI, new String[] {MailboxColumns.ID}, 159ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank WHERE_SERVER_ID_AND_ACCOUNT, mBindArguments, null); 160ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 161ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 162ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public void deleteParser(ArrayList<ContentProviderOperation> ops) throws IOException { 163ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank while (nextTag(EasTags.SYNC_DELETE) != END) { 164ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank switch (tag) { 165ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank case EasTags.FOLDER_SERVER_ID: 166ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank String serverId = getValue(); 167ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // Find the mailbox in this account with the given serverId 168ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank Cursor c = getServerIdCursor(serverId); 169ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank try { 170ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (c.moveToFirst()) { 171ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mService.userLog("Deleting " + serverId); 172ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank ops.add(ContentProviderOperation.newDelete( 173ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank ContentUris.withAppendedId(Mailbox.CONTENT_URI, 174ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank c.getLong(0))).build()); 175ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 176ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } finally { 177ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank c.close(); 178ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 179ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank break; 180ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank default: 181ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank skipTag(); 182ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 183ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 184ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 185ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 186ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public void addParser(ArrayList<ContentProviderOperation> ops) throws IOException { 187ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank String name = null; 188ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank String serverId = null; 189ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank String parentId = null; 190ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank int type = 0; 191ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 192ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank while (nextTag(EasTags.FOLDER_ADD) != END) { 193ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank switch (tag) { 194ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank case EasTags.FOLDER_DISPLAY_NAME: { 195ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank name = getValue(); 196ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank break; 197ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 198ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank case EasTags.FOLDER_TYPE: { 199ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank type = getValueInt(); 200ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank break; 201ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 202ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank case EasTags.FOLDER_PARENT_ID: { 203ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank parentId = getValue(); 204ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank break; 205ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 206ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank case EasTags.FOLDER_SERVER_ID: { 207ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank serverId = getValue(); 208ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank break; 209ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 210ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank default: 211ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank skipTag(); 212ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 213ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 214ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (mValidFolderTypes.contains(type)) { 215ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank Mailbox m = new Mailbox(); 216ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mDisplayName = name; 217ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mServerId = serverId; 218ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mAccountKey = mAccountId; 2196396cfb310b09c53b8e9b51d9ba58d2f6b65c266Andrew Stadler m.mType = Mailbox.TYPE_MAIL; 220ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mSyncFrequency = Account.CHECK_INTERVAL_NEVER; 221ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank switch (type) { 222ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank case INBOX_TYPE: 223ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mSyncFrequency = Account.CHECK_INTERVAL_PUSH; 224ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mType = Mailbox.TYPE_INBOX; 225ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank break; 226ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank case OUTBOX_TYPE: 227ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mSyncFrequency = Account.CHECK_INTERVAL_NEVER; 228ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // TYPE_OUTBOX mailboxes are known by SyncManager to sync whenever they aren't 229ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // empty. The value of mSyncFrequency is ignored for this kind of mailbox. 230ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mType = Mailbox.TYPE_OUTBOX; 231ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank break; 232ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank case SENT_TYPE: 233ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mType = Mailbox.TYPE_SENT; 234ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank break; 235ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank case DRAFTS_TYPE: 236ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mType = Mailbox.TYPE_DRAFTS; 237ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank break; 238ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank case DELETED_TYPE: 239ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mType = Mailbox.TYPE_TRASH; 240ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank break; 241ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank case CALENDAR_TYPE: 242ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mType = Mailbox.TYPE_CALENDAR; 243ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // TODO This could be push, depending on settings 244ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // For now, no sync, since it's not yet implemented 245ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank break; 246ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank case CONTACTS_TYPE: 247ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mType = Mailbox.TYPE_CONTACTS; 248ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // TODO Frequency below should depend on settings 249ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mSyncFrequency = Account.CHECK_INTERVAL_PUSH; 250ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank break; 251ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 252ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 253ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // Make boxes like Contacts and Calendar invisible in the folder list 254ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mFlagVisible = (m.mType < Mailbox.TYPE_NOT_EMAIL); 255ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 256ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (!parentId.equals("0")) { 257ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank m.mParentServerId = parentId; 258ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 259ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 260ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank Log.v(TAG, "Adding mailbox: " + m.mDisplayName); 261ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank ops.add(ContentProviderOperation 262ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank .newInsert(Mailbox.CONTENT_URI).withValues(m.toContentValues()).build()); 263ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 264ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 265ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank return; 266ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 267ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 268ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank public void changesParser() throws IOException { 269ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // Keep track of new boxes, deleted boxes, updated boxes 270ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); 271ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 272ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank while (nextTag(EasTags.FOLDER_CHANGES) != END) { 273ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // TODO Handle FOLDER_CHANGE and FOLDER_DELETE 274ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (tag == EasTags.FOLDER_ADD) { 275ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank addParser(ops); 276ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } else if (tag == EasTags.FOLDER_DELETE) { 277ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank deleteParser(ops); 278ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } else if (tag == EasTags.FOLDER_COUNT) { 279ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank getValueInt(); 280ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } else 281ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank skipTag(); 282ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 283ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 284ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // The mock stream is used for junit tests, so that the parsing code can be tested 285ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // separately from the provider code. 286ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // TODO Change tests to not require this; remove references to the mock stream 287ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (mMock != null) { 288ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mMock.setResult(null); 289ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank return; 290ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 291ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 292ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // Create the new mailboxes in a single batch operation 293ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (!ops.isEmpty()) { 294ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mService.userLog("Applying " + ops.size() + " mailbox operations."); 295ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 296ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // Then, we create an update for the account (most importantly, updating the syncKey) 297ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank ops.add(ContentProviderOperation.newUpdate( 298ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank ContentUris.withAppendedId(Account.CONTENT_URI, mAccountId)).withValues( 299ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mAccount.toContentValues()).build()); 300ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 301ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // Finally, we execute the batch 302ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank try { 303ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mService.mContext.getContentResolver() 304ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank .applyBatch(EmailProvider.EMAIL_AUTHORITY, ops); 30522bc4e0e4f4a5e43e4eea8d59e1961860c507594Marc Blank mService.userLog("New Account SyncKey: " + mAccount.mSyncKey); 306ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } catch (RemoteException e) { 307ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // There is nothing to be done here; fail by returning null 308ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } catch (OperationApplicationException e) { 309ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // There is nothing to be done here; fail by returning null 310ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 311ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 312ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // Look for sync issues and its children and delete them 313ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank // I'm not aware of any other way to deal with this properly 314ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mBindArguments[0] = "Sync Issues"; 315ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mBindArguments[1] = mAccountIdAsString; 316ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank Cursor c = mContentResolver.query(Mailbox.CONTENT_URI, MAILBOX_ID_COLUMNS_PROJECTION, 317ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank WHERE_DISPLAY_NAME_AND_ACCOUNT, mBindArguments, null); 318ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank String parentServerId = null; 319ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank long id = 0; 320ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank try { 321ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (c.moveToFirst()) { 322ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank id = c.getLong(0); 323ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank parentServerId = c.getString(1); 324ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 325ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } finally { 326ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank c.close(); 327ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 328ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank if (parentServerId != null) { 329ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mContentResolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, id), 330ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank null, null); 331ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mBindArguments[0] = parentServerId; 332ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_PARENT_SERVER_ID_AND_ACCOUNT, 333ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank mBindArguments); 334ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 335ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 336ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank } 337ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank 338ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank} 339