Search in sources :

Example 21 with Task

use of com.parse.boltsinternal.Task in project Parse-SDK-Android by ParsePlatform.

the class OfflineStore method saveLocallyAsync.

/**
 * Stores a single object in the local database. If the object is a pointer, isn't dirty, and
 * has an objectId already, it may not be saved, since it would provide no useful data.
 *
 * @param object The object to save.
 * @param db A database connection to use.
 */
private Task<Void> saveLocallyAsync(final String key, final ParseObject object, final ParseSQLiteDatabase db) {
    // If this is just a clean, unfetched pointer known to Parse, then there is nothing to save.
    if (object.getObjectId() != null && !object.isDataAvailable() && !object.hasChanges() && !object.hasOutstandingOperations()) {
        return Task.forResult(null);
    }
    final Capture<String> uuidCapture = new Capture<>();
    // Make sure we have a UUID for the object to be saved.
    return getOrCreateUUIDAsync(object, db).onSuccessTask(task -> {
        String uuid = task.getResult();
        uuidCapture.set(uuid);
        return updateDataForObjectAsync(uuid, object, db);
    }).onSuccessTask(task -> {
        final ContentValues values = new ContentValues();
        values.put(OfflineSQLiteOpenHelper.KEY_KEY, key);
        values.put(OfflineSQLiteOpenHelper.KEY_UUID, uuidCapture.get());
        return db.insertWithOnConflict(OfflineSQLiteOpenHelper.TABLE_DEPENDENCIES, values, SQLiteDatabase.CONFLICT_IGNORE);
    });
}
Also used : Context(android.content.Context) Arrays(java.util.Arrays) ConstraintMatcher(com.parse.OfflineQueryLogic.ConstraintMatcher) Pair(android.util.Pair) TextUtils(android.text.TextUtils) HashMap(java.util.HashMap) UUID(java.util.UUID) ArrayList(java.util.ArrayList) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) List(java.util.List) JSONException(org.json.JSONException) Capture(com.parse.boltsinternal.Capture) Continuation(com.parse.boltsinternal.Continuation) JSONObject(org.json.JSONObject) Map(java.util.Map) ContentValues(android.content.ContentValues) LinkedList(java.util.LinkedList) Task(com.parse.boltsinternal.Task) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) WeakHashMap(java.util.WeakHashMap) Cursor(android.database.Cursor) ContentValues(android.content.ContentValues) Capture(com.parse.boltsinternal.Capture)

Example 22 with Task

use of com.parse.boltsinternal.Task in project Parse-SDK-Android by ParsePlatform.

the class ParseCommandCache method maybeRunAllCommandsNow.

/**
 * Attempts to run every command in the disk queue in order, synchronously. If there is no
 * network connection, returns immediately without doing anything. If there is supposedly a
 * connection, but parse can't be reached, waits timeoutRetryWaitSeconds before retrying up to
 * retriesRemaining times. Blocks until either there's a connection, or the retries are
 * exhausted. If any command fails, just deletes it and moves on to the next one.
 */
private void maybeRunAllCommandsNow(int retriesRemaining) {
    synchronized (lock) {
        unprocessedCommandsExist = false;
        if (!isConnected()) {
            // There's no way to do work when there's no network connection.
            return;
        }
        String[] fileNames = cachePath.list();
        if (fileNames == null || fileNames.length == 0) {
            return;
        }
        Arrays.sort(fileNames);
        for (String fileName : fileNames) {
            final File file = new File(cachePath, fileName);
            // Read one command from the cache.
            JSONObject json;
            try {
                json = ParseFileUtils.readFileToJSONObject(file);
            } catch (FileNotFoundException e) {
                // This shouldn't really be possible.
                if (Parse.LOG_LEVEL_ERROR >= Parse.getLogLevel()) {
                    log.log(Level.SEVERE, "File disappeared from cache while being read.", e);
                }
                continue;
            } catch (IOException e) {
                if (Parse.LOG_LEVEL_ERROR >= Parse.getLogLevel()) {
                    log.log(Level.SEVERE, "Unable to read contents of file in cache.", e);
                }
                removeFile(file);
                continue;
            } catch (JSONException e) {
                if (Parse.LOG_LEVEL_ERROR >= Parse.getLogLevel()) {
                    log.log(Level.SEVERE, "Error parsing JSON found in cache.", e);
                }
                removeFile(file);
                continue;
            }
            // Convert the command from a string.
            final ParseRESTCommand command;
            final TaskCompletionSource<JSONObject> tcs = pendingTasks.containsKey(file) ? pendingTasks.get(file) : null;
            try {
                command = commandFromJSON(json);
            } catch (JSONException e) {
                if (Parse.LOG_LEVEL_ERROR >= Parse.getLogLevel()) {
                    log.log(Level.SEVERE, "Unable to create ParseCommand from JSON.", e);
                }
                removeFile(file);
                continue;
            }
            try {
                Task<JSONObject> commandTask;
                if (command == null) {
                    commandTask = Task.forResult(null);
                    if (tcs != null) {
                        tcs.setResult(null);
                    }
                    notifyTestHelper(TestHelper.COMMAND_OLD_FORMAT_DISCARDED);
                } else {
                    commandTask = command.executeAsync(httpClient).continueWithTask(task -> {
                        String localId = command.getLocalId();
                        Exception error = task.getError();
                        if (error != null) {
                            if (!(error instanceof ParseException) || ((ParseException) error).getCode() != ParseException.CONNECTION_FAILED) {
                                if (tcs != null) {
                                    tcs.setError(error);
                                }
                            }
                            return task;
                        }
                        JSONObject json1 = task.getResult();
                        if (tcs != null) {
                            tcs.setResult(json1);
                        } else if (localId != null) {
                            // If this command created a new objectId,
                            // add it to the map.
                            String objectId = json1.optString("objectId", null);
                            if (objectId != null) {
                                ParseCorePlugins.getInstance().getLocalIdManager().setObjectId(localId, objectId);
                            }
                        }
                        return task;
                    });
                }
                waitForTaskWithoutLock(commandTask);
                if (tcs != null) {
                    waitForTaskWithoutLock(tcs.getTask());
                }
                // The command succeeded. Remove it from the cache.
                removeFile(file);
                notifyTestHelper(TestHelper.COMMAND_SUCCESSFUL);
            } catch (ParseException e) {
                if (e.getCode() == ParseException.CONNECTION_FAILED) {
                    if (retriesRemaining > 0) {
                        // anything else.
                        if (Parse.LOG_LEVEL_INFO >= Parse.getLogLevel()) {
                            log.info("Network timeout in command cache. Waiting for " + timeoutRetryWaitSeconds + " seconds and then retrying " + retriesRemaining + " times.");
                        }
                        long currentTime = System.currentTimeMillis();
                        long waitUntil = currentTime + (long) (timeoutRetryWaitSeconds * 1000);
                        while (currentTime < waitUntil) {
                            // or should stop, just quit.
                            if (!isConnected() || shouldStop) {
                                if (Parse.LOG_LEVEL_INFO >= Parse.getLogLevel()) {
                                    log.info("Aborting wait because runEventually thread should stop.");
                                }
                                return;
                            }
                            try {
                                lock.wait(waitUntil - currentTime);
                            } catch (InterruptedException ie) {
                                shouldStop = true;
                            }
                            currentTime = System.currentTimeMillis();
                            if (currentTime < (waitUntil - (long) (timeoutRetryWaitSeconds * 1000))) {
                                // This situation should be impossible, so it must mean the
                                // clock changed.
                                currentTime = (waitUntil - (long) (timeoutRetryWaitSeconds * 1000));
                            }
                        }
                        maybeRunAllCommandsNow(retriesRemaining - 1);
                    } else {
                        setConnected(false);
                        notifyTestHelper(TestHelper.NETWORK_DOWN);
                    }
                } else {
                    if (Parse.LOG_LEVEL_ERROR >= Parse.getLogLevel()) {
                        log.log(Level.SEVERE, "Failed to run command.", e);
                    }
                    // Delete the command from the cache, even though it failed.
                    // Otherwise, we'll just keep trying it forever.
                    removeFile(file);
                    notifyTestHelper(TestHelper.COMMAND_FAILED, e);
                }
            }
        }
    }
}
Also used : ConnectivityManager(android.net.ConnectivityManager) Context(android.content.Context) Arrays(java.util.Arrays) IOException(java.io.IOException) HashMap(java.util.HashMap) Callable(java.util.concurrent.Callable) Logger(java.util.logging.Logger) File(java.io.File) FileNotFoundException(java.io.FileNotFoundException) Level(java.util.logging.Level) Manifest(android.Manifest) JSONException(org.json.JSONException) Capture(com.parse.boltsinternal.Capture) Continuation(com.parse.boltsinternal.Continuation) JSONObject(org.json.JSONObject) Task(com.parse.boltsinternal.Task) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) UnsupportedEncodingException(java.io.UnsupportedEncodingException) FileNotFoundException(java.io.FileNotFoundException) JSONException(org.json.JSONException) IOException(java.io.IOException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) JSONException(org.json.JSONException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) JSONObject(org.json.JSONObject) File(java.io.File)

Example 23 with Task

use of com.parse.boltsinternal.Task in project Parse-SDK-Android by ParsePlatform.

the class ParseFile method getDataInBackground.

/**
 * Asynchronously gets the data from cache if available or fetches its content from the network.
 * A {@code ProgressCallback} will be called periodically with progress updates.
 *
 * @param progressCallback A {@code ProgressCallback} that is called periodically with progress
 *     updates.
 * @return A Task that is resolved when the data has been fetched.
 */
public Task<byte[]> getDataInBackground(final ProgressCallback progressCallback) {
    final TaskCompletionSource<Void> cts = new TaskCompletionSource<>();
    currentTasks.add(cts);
    return taskQueue.enqueue(toAwait -> fetchInBackground(progressCallback, toAwait, cts.getTask()).onSuccess(task -> {
        File file = task.getResult();
        try {
            return ParseFileUtils.readFileToByteArray(file);
        } catch (IOException e) {
        // do nothing
        }
        return null;
    })).continueWithTask(task -> {
        // release
        cts.trySetResult(null);
        currentTasks.remove(cts);
        return task;
    });
}
Also used : Parcelable(android.os.Parcelable) Set(java.util.Set) IOException(java.io.IOException) Callable(java.util.concurrent.Callable) FileInputStream(java.io.FileInputStream) Parcel(android.os.Parcel) File(java.io.File) HashSet(java.util.HashSet) JSONException(org.json.JSONException) Continuation(com.parse.boltsinternal.Continuation) JSONObject(org.json.JSONObject) Task(com.parse.boltsinternal.Task) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) Collections(java.util.Collections) InputStream(java.io.InputStream) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) IOException(java.io.IOException) File(java.io.File)

Example 24 with Task

use of com.parse.boltsinternal.Task in project Parse-SDK-Android by ParsePlatform.

the class OfflineQueryLogic method createMatcher.

/**
 * Returns a ConstraintMatcher that return true iff the object matches QueryConstraints. This
 * takes in a SQLiteDatabase connection because SQLite is finicky about nesting connections, so
 * we want to reuse them whenever possible.
 */
private <T extends ParseObject> ConstraintMatcher<T> createMatcher(ParseUser user, QueryConstraints queryConstraints) {
    // Make a list of all the matchers to AND together.
    final ArrayList<ConstraintMatcher<T>> matchers = new ArrayList<>();
    for (final String key : queryConstraints.keySet()) {
        final Object queryConstraintValue = queryConstraints.get(key);
        if (key.equals("$or")) {
            /*
                 * A set of queries to be OR-ed together.
                 */
            @SuppressWarnings("unchecked") ConstraintMatcher<T> matcher = createOrMatcher(user, (ArrayList<QueryConstraints>) queryConstraintValue);
            matchers.add(matcher);
        } else if (queryConstraintValue instanceof KeyConstraints) {
            /*
                 * It's a set of constraints that should be AND-ed together.
                 */
            KeyConstraints keyConstraints = (KeyConstraints) queryConstraintValue;
            for (String operator : keyConstraints.keySet()) {
                final Object keyConstraintValue = keyConstraints.get(operator);
                ConstraintMatcher<T> matcher = createMatcher(user, operator, keyConstraintValue, key, keyConstraints);
                matchers.add(matcher);
            }
        } else if (queryConstraintValue instanceof RelationConstraint) {
            /*
                 * It's a $relatedTo constraint.
                 */
            final RelationConstraint relation = (RelationConstraint) queryConstraintValue;
            matchers.add(new ConstraintMatcher<T>(user) {

                @Override
                public Task<Boolean> matchesAsync(T object, ParseSQLiteDatabase db) {
                    return Task.forResult(relation.getRelation().hasKnownObject(object));
                }
            });
        } else {
            /*
                 * It's not a set of constraints, so it's just a value to compare against.
                 */
            matchers.add(new ConstraintMatcher<T>(user) {

                @Override
                public Task<Boolean> matchesAsync(T object, ParseSQLiteDatabase db) {
                    Object objectValue;
                    try {
                        objectValue = getValue(object, key);
                    } catch (ParseException e) {
                        return Task.forError(e);
                    }
                    return Task.forResult(matchesEqualConstraint(queryConstraintValue, objectValue));
                }
            });
        }
    }
    /*
         * Now AND together the constraints for each key.
         */
    return new ConstraintMatcher<T>(user) {

        @Override
        public Task<Boolean> matchesAsync(final T object, final ParseSQLiteDatabase db) {
            Task<Boolean> task = Task.forResult(true);
            for (final ConstraintMatcher<T> matcher : matchers) {
                task = task.onSuccessTask(task1 -> {
                    if (!task1.getResult()) {
                        return task1;
                    }
                    return matcher.matchesAsync(object, db);
                });
            }
            return task;
        }
    };
}
Also used : Date(java.util.Date) Collection(java.util.Collection) RelationConstraint(com.parse.ParseQuery.RelationConstraint) Set(java.util.Set) HashMap(java.util.HashMap) KeyConstraints(com.parse.ParseQuery.KeyConstraints) ArrayList(java.util.ArrayList) List(java.util.List) JSONException(org.json.JSONException) QueryConstraints(com.parse.ParseQuery.QueryConstraints) Matcher(java.util.regex.Matcher) JSONObject(org.json.JSONObject) Map(java.util.Map) Pattern(java.util.regex.Pattern) Task(com.parse.boltsinternal.Task) Collections(java.util.Collections) JSONArray(org.json.JSONArray) Task(com.parse.boltsinternal.Task) ArrayList(java.util.ArrayList) QueryConstraints(com.parse.ParseQuery.QueryConstraints) RelationConstraint(com.parse.ParseQuery.RelationConstraint) JSONObject(org.json.JSONObject) KeyConstraints(com.parse.ParseQuery.KeyConstraints)

Aggregations

Task (com.parse.boltsinternal.Task)24 ArrayList (java.util.ArrayList)15 JSONObject (org.json.JSONObject)15 Continuation (com.parse.boltsinternal.Continuation)11 TaskCompletionSource (com.parse.boltsinternal.TaskCompletionSource)11 HashMap (java.util.HashMap)11 List (java.util.List)11 JSONException (org.json.JSONException)11 Map (java.util.Map)9 Capture (com.parse.boltsinternal.Capture)8 ContentValues (android.content.ContentValues)7 Context (android.content.Context)7 Cursor (android.database.Cursor)7 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)7 Test (org.junit.Test)7 Arrays (java.util.Arrays)6 Set (java.util.Set)6 JSONArray (org.json.JSONArray)6 TextUtils (android.text.TextUtils)5 Pair (android.util.Pair)5