blob: 8f5e64ecb91afa785427bd80f1207b3c1669bf53 [file] [log] [blame]
package com.android.exchange.service;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.SyncResult;
import android.os.Bundle;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent.HostAuthColumns;
import com.android.emailcommon.provider.Mailbox;
import com.android.exchange.CommandStatusException;
import com.android.exchange.CommandStatusException.CommandStatus;
import com.android.exchange.EasResponse;
import com.android.exchange.adapter.FolderSyncParser;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags;
import org.apache.http.HttpStatus;
import java.io.IOException;
import java.io.InputStream;
/**
* Performs an Exchange Account sync, which includes folder sync.
*/
public class EasAccountSyncHandler extends EasSyncHandler {
public EasAccountSyncHandler(final Context context, final ContentResolver contentResolver,
final Account account, final Mailbox mailbox, final Bundle syncExtras,
final SyncResult syncResult) {
super(context, contentResolver, account, mailbox, syncExtras, syncResult);
}
@Override
public SyncStatus performSync() {
boolean needsResync;
do {
needsResync = false;
final EasResponse resp;
try {
final Serializer s = new Serializer();
s.start(Tags.FOLDER_FOLDER_SYNC).start(Tags.FOLDER_SYNC_KEY)
.text(mAccount.mSyncKey).end().end().done();
resp = sendHttpClientPost("FolderSync", s.toByteArray());
} catch (final IOException e) {
return SyncStatus.FAILURE_IO;
}
try {
final int code = resp.getStatus();
if (code == HttpStatus.SC_OK) {
if (!resp.isEmpty()) {
final InputStream is = resp.getInputStream();
try {
// Returns true if we need to sync again
// TODO: FolderSyncParser needs to be cleaned up to remove dependency
// on AbstractSyncAdapter.
if (new FolderSyncParser(mContext, mContentResolver, is, mAccount,
mMailbox, false).parse()) {
needsResync = true;
}
} catch (final IOException e) {
return SyncStatus.FAILURE_IO;
} catch (final CommandStatusException e) {
final int status = e.mStatus;
if (CommandStatus.isNeedsProvisioning(status)) {
// TODO: Attempt provisioning.
return SyncStatus.FAILURE_SECURITY;
}
return SyncStatus.FAILURE_OTHER;
}
}
} else if (EasResponse.isProvisionError(code)) {
// TODO: Attempt provisioning.
return SyncStatus.FAILURE_SECURITY;
} else if (EasResponse.isAuthError(code)) {
return SyncStatus.FAILURE_LOGIN;
} else if (EasResponse.isRedirectError(code)) {
if (redirectHostAuth(resp.getRedirectAddress())) {
needsResync = true;
} else {
// TODO: Perhaps a more severe error here?
return SyncStatus.FAILURE_LOGIN;
}
}
} finally {
resp.close();
}
} while (needsResync);
return SyncStatus.SUCCESS;
}
/**
* Reset our local HostAuth's address and save the change to the DB.
* @param newAddress The new address for the HostAuth.
* @return Whether the redirect was processed.
*/
private boolean redirectHostAuth(final String newAddress) {
if (newAddress != null) {
mHostAuth.mAddress = newAddress;
final ContentValues haValues = new ContentValues(1);
haValues.put(HostAuthColumns.ADDRESS, newAddress);
mHostAuth.update(mContext, haValues);
// TODO: When we start caching connections, make sure to uncache here.
}
return newAddress != null;
}
}