<commit_before>package org.commcare.tasks;

import android.content.Context;
import android.content.Intent;
import android.support.v4.util.Pair;

import net.sqlcipher.database.SQLiteDatabase;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.conn.ConnectTimeoutException;
import org.commcare.CommCareApplication;
import org.commcare.android.database.app.models.UserKeyRecord;
import org.commcare.android.database.user.models.ACase;
import org.commcare.data.xml.DataModelPullParser;
import org.commcare.engine.cases.CaseUtils;
import org.commcare.interfaces.HttpRequestEndpoints;
import org.commcare.logging.AndroidLogger;
import org.commcare.logging.analytics.GoogleAnalyticsFields;
import org.commcare.models.database.SqlStorage;
import org.commcare.models.encryption.ByteEncrypter;
import org.commcare.core.encryption.CryptUtil;
import org.commcare.modern.models.RecordTooLargeException;
import org.commcare.network.DataPullRequester;
import org.commcare.network.RemoteDataPullResponse;
import org.commcare.preferences.CommCarePreferences;
import org.commcare.resources.model.CommCareOTARestoreListener;
import org.commcare.services.CommCareSessionService;
import org.commcare.tasks.templates.CommCareTask;
import org.commcare.utils.FormSaveUtil;
import org.commcare.utils.SessionUnavailableException;
import org.commcare.utils.UnknownSyncError;
import org.commcare.core.network.bitcache.BitCache;
import org.commcare.xml.AndroidTransactionParserFactory;
import org.javarosa.core.model.User;
import org.javarosa.core.services.Logger;
import org.javarosa.core.services.locale.Localization;
import org.javarosa.core.services.storage.StorageFullException;
import org.javarosa.core.util.PropertyUtils;
import org.javarosa.xml.util.ActionableInvalidStructureException;
import org.javarosa.xml.util.InvalidStructureException;
import org.javarosa.xml.util.UnfullfilledRequirementsException;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Hashtable;
import java.util.NoSuchElementException;

import javax.crypto.SecretKey;

/**
 * @author ctsims
 */
public abstract class DataPullTask<R> 
    extends CommCareTask<Void, Integer, ResultAndError<DataPullTask.PullTaskResult>, R>
        implements CommCareOTARestoreListener {
    private final String server;
    private final String username;
    private final String password;
    protected final Context context;

    private int mCurrentProgress;
    private int mTotalItems;
    private long mSyncStartTime;

    public static final int DATA_PULL_TASK_ID = 10;

    public static final int PROGRESS_STARTED = 0;
    public static final int PROGRESS_CLEANED = 1;
    public static final int PROGRESS_AUTHED = 2;
    private static final int PROGRESS_DONE = 4;
    public static final int PROGRESS_RECOVERY_NEEDED = 8;
    public static final int PROGRESS_RECOVERY_STARTED = 16;
    private static final int PROGRESS_RECOVERY_FAIL_SAFE = 32;
    private static final int PROGRESS_RECOVERY_FAIL_BAD = 64;
    public static final int PROGRESS_PROCESSING = 128;
    public static final int PROGRESS_DOWNLOADING = 256;
    public static final int PROGRESS_DOWNLOADING_COMPLETE = 512;
    public static final int PROGRESS_SERVER_PROCESSING = 1024;

    private final DataPullRequester dataPullRequester;
    private final AsyncRestoreHelper asyncRestoreHelper;
    private final boolean blockRemoteKeyManagement;

    private boolean loginNeeded;
    private UserKeyRecord ukrForLogin;
    private boolean wasKeyLoggedIn;

    public DataPullTask(String username, String password,
                        String server, Context context, DataPullRequester dataPullRequester,
                        boolean blockRemoteKeyManagement) {
        this.server = server;
        this.username = username;
        this.password = password;
        this.context = context;
        this.taskId = DATA_PULL_TASK_ID;
        this.dataPullRequester = dataPullRequester;
        this.requestor = dataPullRequester.getHttpGenerator(username, password);
        this.asyncRestoreHelper = new AsyncRestoreHelper(this);
        this.blockRemoteKeyManagement = blockRemoteKeyManagement;

        TAG = DataPullTask.class.getSimpleName();
    }

    public DataPullTask(String username, String password,
                        String server, Context context) {
        this(username, password, server, context, CommCareApplication._().getDataPullRequester(),
                false);
    }

    // TODO PLM: once this task is refactored into manageable components, it should use the
    // ManagedAsyncTask pattern of checking for isCancelled() and aborting at safe places.
    @Override
    protected void onCancelled() {
        super.onCancelled();
        wipeLoginIfItOccurred();
    }
    private final HttpRequestEndpoints requestor;

    @Override
    protected ResultAndError<PullTaskResult> doTaskBackground(Void... params) {
        if (!CommCareSessionService.sessionAliveLock.tryLock()) {
            // Don't try to sync if logging out is occurring
            return new ResultAndError<>(PullTaskResult.UNKNOWN_FAILURE,
                    "Cannot sync while a logout is in process");
        }
        try {
            return doTaskBackgroundHelper();
        } finally {
            CommCareSessionService.sessionAliveLock.unlock();
        }
    }

    @Override
    public void refreshView() {
        
    }

    private ResultAndError<PullTaskResult> doTaskBackgroundHelper() {
        publishProgress(PROGRESS_STARTED);
        recordSyncAttemptTime();
        Logger.log(AndroidLogger.TYPE_USER, "Starting Sync");
        determineIfLoginNeeded();

        AndroidTransactionParserFactory factory = getTransactionParserFactory();
        byte[] wrappedEncryptionKey = getEncryptionKey();
        if (wrappedEncryptionKey == null) {
            this.publishProgress(PROGRESS_DONE);
            return new ResultAndError<>(PullTaskResult.UNKNOWN_FAILURE,
                    "Unable to get or generate encryption key");
        }

        factory.initUserParser(wrappedEncryptionKey);
        if (!loginNeeded) {
            //Only purge cases if we already had a logged in user. Otherwise we probably can't read the DB.
            CaseUtils.purgeCases();
        }

        return getRequestResultOrRetry(factory);
    }<commit_msg>Revert "add back method required by implementing interface"<commit_after>package org.commcare.tasks;

import android.content.Context;
import android.content.Intent;
import android.support.v4.util.Pair;

import net.sqlcipher.database.SQLiteDatabase;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.conn.ConnectTimeoutException;
import org.commcare.CommCareApplication;
import org.commcare.android.database.app.models.UserKeyRecord;
import org.commcare.android.database.user.models.ACase;
import org.commcare.data.xml.DataModelPullParser;
import org.commcare.engine.cases.CaseUtils;
import org.commcare.interfaces.HttpRequestEndpoints;
import org.commcare.logging.AndroidLogger;
import org.commcare.logging.analytics.GoogleAnalyticsFields;
import org.commcare.models.database.SqlStorage;
import org.commcare.models.encryption.ByteEncrypter;
import org.commcare.core.encryption.CryptUtil;
import org.commcare.modern.models.RecordTooLargeException;
import org.commcare.network.DataPullRequester;
import org.commcare.network.RemoteDataPullResponse;
import org.commcare.preferences.CommCarePreferences;
import org.commcare.resources.model.CommCareOTARestoreListener;
import org.commcare.services.CommCareSessionService;
import org.commcare.tasks.templates.CommCareTask;
import org.commcare.utils.FormSaveUtil;
import org.commcare.utils.SessionUnavailableException;
import org.commcare.utils.UnknownSyncError;
import org.commcare.core.network.bitcache.BitCache;
import org.commcare.xml.AndroidTransactionParserFactory;
import org.javarosa.core.model.User;
import org.javarosa.core.services.Logger;
import org.javarosa.core.services.locale.Localization;
import org.javarosa.core.services.storage.StorageFullException;
import org.javarosa.core.util.PropertyUtils;
import org.javarosa.xml.util.ActionableInvalidStructureException;
import org.javarosa.xml.util.InvalidStructureException;
import org.javarosa.xml.util.UnfullfilledRequirementsException;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Hashtable;
import java.util.NoSuchElementException;

import javax.crypto.SecretKey;

/**
 * @author ctsims
 */
public abstract class DataPullTask<R> 
    extends CommCareTask<Void, Integer, ResultAndError<DataPullTask.PullTaskResult>, R>
        implements CommCareOTARestoreListener {
    private final String server;
    private final String username;
    private final String password;
    protected final Context context;

    private int mCurrentProgress;
    private int mTotalItems;
    private long mSyncStartTime;

    public static final int DATA_PULL_TASK_ID = 10;

    public static final int PROGRESS_STARTED = 0;
    public static final int PROGRESS_CLEANED = 1;
    public static final int PROGRESS_AUTHED = 2;
    private static final int PROGRESS_DONE = 4;
    public static final int PROGRESS_RECOVERY_NEEDED = 8;
    public static final int PROGRESS_RECOVERY_STARTED = 16;
    private static final int PROGRESS_RECOVERY_FAIL_SAFE = 32;
    private static final int PROGRESS_RECOVERY_FAIL_BAD = 64;
    public static final int PROGRESS_PROCESSING = 128;
    public static final int PROGRESS_DOWNLOADING = 256;
    public static final int PROGRESS_DOWNLOADING_COMPLETE = 512;
    public static final int PROGRESS_SERVER_PROCESSING = 1024;

    private final DataPullRequester dataPullRequester;
    private final AsyncRestoreHelper asyncRestoreHelper;
    private final boolean blockRemoteKeyManagement;

    private boolean loginNeeded;
    private UserKeyRecord ukrForLogin;
    private boolean wasKeyLoggedIn;

    public DataPullTask(String username, String password,
                        String server, Context context, DataPullRequester dataPullRequester,
                        boolean blockRemoteKeyManagement) {
        this.server = server;
        this.username = username;
        this.password = password;
        this.context = context;
        this.taskId = DATA_PULL_TASK_ID;
        this.dataPullRequester = dataPullRequester;
        this.requestor = dataPullRequester.getHttpGenerator(username, password);
        this.asyncRestoreHelper = new AsyncRestoreHelper(this);
        this.blockRemoteKeyManagement = blockRemoteKeyManagement;

        TAG = DataPullTask.class.getSimpleName();
    }

    public DataPullTask(String username, String password,
                        String server, Context context) {
        this(username, password, server, context, CommCareApplication._().getDataPullRequester(),
                false);
    }

    // TODO PLM: once this task is refactored into manageable components, it should use the
    // ManagedAsyncTask pattern of checking for isCancelled() and aborting at safe places.
    @Override
    protected void onCancelled() {
        super.onCancelled();
        wipeLoginIfItOccurred();
    }
    private final HttpRequestEndpoints requestor;

    @Override
    protected ResultAndError<PullTaskResult> doTaskBackground(Void... params) {
        if (!CommCareSessionService.sessionAliveLock.tryLock()) {
            // Don't try to sync if logging out is occurring
            return new ResultAndError<>(PullTaskResult.UNKNOWN_FAILURE,
                    "Cannot sync while a logout is in process");
        }
        try {
            return doTaskBackgroundHelper();
        } finally {
            CommCareSessionService.sessionAliveLock.unlock();
        }
    }

    private ResultAndError<PullTaskResult> doTaskBackgroundHelper() {
        publishProgress(PROGRESS_STARTED);
        recordSyncAttemptTime();
        Logger.log(AndroidLogger.TYPE_USER, "Starting Sync");
        determineIfLoginNeeded();

        AndroidTransactionParserFactory factory = getTransactionParserFactory();
        byte[] wrappedEncryptionKey = getEncryptionKey();
        if (wrappedEncryptionKey == null) {
            this.publishProgress(PROGRESS_DONE);
            return new ResultAndError<>(PullTaskResult.UNKNOWN_FAILURE,
                    "Unable to get or generate encryption key");
        }

        factory.initUserParser(wrappedEncryptionKey);
        if (!loginNeeded) {
            //Only purge cases if we already had a logged in user. Otherwise we probably can't read the DB.
            CaseUtils.purgeCases();
        }

        return getRequestResultOrRetry(factory);
    }
{'fraction_non_alphanumeric': 0.07388973966309341, 'fraction_numerical': 0.004287901990811639, 'mean_word_length': 3.8590029761904763, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 12}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4253893', 'n_tokens_mistral': 3682, 'n_tokens_neox': 3545, 'n_words': 823}