Search in sources :

Example 6 with Task

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

the class ParseCloudTest method testCallFunctionAsync.

// endregion
// region testCallFunctions
@Test
public void testCallFunctionAsync() throws Exception {
    ParseCloudCodeController controller = mockParseCloudCodeControllerWithResponse("result");
    ParseCorePlugins.getInstance().registerCloudCodeController(controller);
    Map<String, Object> parameters = new HashMap<>();
    parameters.put("key1", Arrays.asList(1, 2, 3));
    parameters.put("key2", "value1");
    Task cloudCodeTask = ParseCloud.callFunctionInBackground("name", parameters);
    ParseTaskUtils.wait(cloudCodeTask);
    verify(controller, times(1)).callFunctionInBackground(eq("name"), eq(parameters), isNull());
    assertTrue(cloudCodeTask.isCompleted());
    assertNull(cloudCodeTask.getError());
    assertThat(cloudCodeTask.getResult(), instanceOf(String.class));
    assertEquals("result", cloudCodeTask.getResult());
}
Also used : Task(com.parse.boltsinternal.Task) HashMap(java.util.HashMap) Matchers.anyString(org.mockito.Matchers.anyString) Test(org.junit.Test)

Example 7 with Task

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

the class OfflineStore method fetchLocallyAsync.

/**
 * Gets the data for the given object from the offline database. Returns a task that will be
 * completed if data for the object was available. If the object is not in the cache, the task
 * will be faulted, with a CACHE_MISS error.
 *
 * @param object The object to fetch.
 * @param db A database connection to use.
 */
/* package for OfflineQueryLogic */
<T extends ParseObject> Task<T> fetchLocallyAsync(final T object, final ParseSQLiteDatabase db) {
    final TaskCompletionSource<T> tcs = new TaskCompletionSource<>();
    Task<String> uuidTask;
    synchronized (lock) {
        if (fetchedObjects.containsKey(object)) {
            // noinspection unchecked
            return (Task<T>) fetchedObjects.get(object);
        }
        /*
             * Put a placeholder so that anyone else who attempts to fetch this object will just wait for
             * this call to finish doing it.
             */
        // noinspection unchecked
        fetchedObjects.put(object, (Task<ParseObject>) tcs.getTask());
        uuidTask = objectToUuidMap.get(object);
    }
    String className = object.getClassName();
    String objectId = object.getObjectId();
    /*
         * If this gets set, then it will contain data from the offline store that needs to be merged
         * into the existing object in memory.
         */
    Task<String> jsonStringTask = Task.forResult(null);
    if (objectId == null) {
        // This Object has never been saved to Parse.
        if (uuidTask == null) {
        /*
                 * This object was not pulled from the data store or previously saved to it, so there's
                 * nothing that can be fetched from it. This isn't an error, because it's really convenient
                 * to try to fetch objects from the offline store just to make sure they are up-to-date, and
                 * we shouldn't force developers to specially handle this case.
                 */
        } else {
            /*
                 * This object is a new ParseObject that is known to the data store, but hasn't been
                 * fetched. The only way this could happen is if the object had previously been stored in
                 * the offline store, then the object was removed from memory (maybe by rebooting), and then
                 * a object with a pointer to it was fetched, so we only created the pointer. We need to
                 * pull the data out of the database using the UUID.
                 */
            final String[] select = { OfflineSQLiteOpenHelper.KEY_JSON };
            final String where = OfflineSQLiteOpenHelper.KEY_UUID + " = ?";
            final Capture<String> uuid = new Capture<>();
            jsonStringTask = uuidTask.onSuccessTask(task -> {
                uuid.set(task.getResult());
                String[] args = { uuid.get() };
                return db.queryAsync(OfflineSQLiteOpenHelper.TABLE_OBJECTS, select, where, args);
            }).onSuccess(task -> {
                Cursor cursor = task.getResult();
                cursor.moveToFirst();
                if (cursor.isAfterLast()) {
                    cursor.close();
                    throw new IllegalStateException("Attempted to find non-existent uuid " + uuid.get());
                }
                String json = cursor.getString(0);
                cursor.close();
                return json;
            });
        }
    } else {
        if (uuidTask != null) {
            /*
                 * This object is an existing ParseObject, and we must've already pulled its data out of the
                 * offline store, or else we wouldn't know its UUID. This should never happen.
                 */
            tcs.setError(new IllegalStateException("This object must have already been " + "fetched from the local datastore, but isn't marked as fetched."));
            synchronized (lock) {
                // Forget we even tried to fetch this object, so that retries will actually...
                // retry.
                fetchedObjects.remove(object);
            }
            return tcs.getTask();
        }
        /*
             * We've got a pointer to an existing ParseObject, but we've never pulled its data out of the
             * offline store. Since fetching from the server forces a fetch from the offline store, that
             * means this is a pointer. We need to try to find any existing entry for this object in the
             * database.
             */
        String[] select = { OfflineSQLiteOpenHelper.KEY_JSON, OfflineSQLiteOpenHelper.KEY_UUID };
        String where = String.format("%s = ? AND %s = ?", OfflineSQLiteOpenHelper.KEY_CLASS_NAME, OfflineSQLiteOpenHelper.KEY_OBJECT_ID);
        String[] args = { className, objectId };
        jsonStringTask = db.queryAsync(OfflineSQLiteOpenHelper.TABLE_OBJECTS, select, where, args).onSuccess(task -> {
            Cursor cursor = task.getResult();
            cursor.moveToFirst();
            if (cursor.isAfterLast()) {
                /*
                                             * This is a pointer that came from Parse that references an object that has
                                             * never been saved in the offline store before. This just means there's no data
                                             * in the store that needs to be merged into the object.
                                             */
                cursor.close();
                throw new ParseException(ParseException.CACHE_MISS, "This object is not available in the offline cache.");
            }
            // we should fetch its data and record its UUID for future
            // reference.
            String jsonString = cursor.getString(0);
            String newUUID = cursor.getString(1);
            cursor.close();
            synchronized (lock) {
                /*
                                             * It's okay to put this object into the uuid map. No one will try to fetch
                                             * it, because it's already in the fetchedObjects map. And no one will try to
                                             * save to it without fetching it first, so everything should be just fine.
                                             */
                objectToUuidMap.put(object, Task.forResult(newUUID));
                uuidToObjectMap.put(newUUID, object);
            }
            return jsonString;
        });
    }
    return jsonStringTask.onSuccessTask((Continuation<String, Task<Void>>) task -> {
        String jsonString = task.getResult();
        if (jsonString == null) {
            return Task.forError(new ParseException(ParseException.CACHE_MISS, "Attempted to fetch an object offline which was never saved to the offline cache."));
        }
        final JSONObject json;
        try {
            json = new JSONObject(jsonString);
        } catch (JSONException e) {
            return Task.forError(e);
        }
        final Map<String, Task<ParseObject>> offlineObjects = new HashMap<>();
        (new ParseTraverser() {

            @Override
            protected boolean visit(Object object1) {
                if (object1 instanceof JSONObject && ((JSONObject) object1).optString("__type").equals("OfflineObject")) {
                    String uuid = ((JSONObject) object1).optString("uuid");
                    offlineObjects.put(uuid, getPointerAsync(uuid, db));
                }
                return true;
            }
        }).setTraverseParseObjects(false).setYieldRoot(false).traverse(json);
        return Task.whenAll(offlineObjects.values()).onSuccess(task1 -> {
            object.mergeREST(object.getState(), json, new OfflineDecoder(offlineObjects));
            return null;
        });
    }).continueWithTask(task -> {
        if (task.isCancelled()) {
            tcs.setCancelled();
        } else if (task.isFaulted()) {
            tcs.setError(task.getError());
        } else {
            tcs.setResult(object);
        }
        return tcs.getTask();
    });
}
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) Task(com.parse.boltsinternal.Task) Continuation(com.parse.boltsinternal.Continuation) HashMap(java.util.HashMap) WeakHashMap(java.util.WeakHashMap) JSONException(org.json.JSONException) Cursor(android.database.Cursor) Capture(com.parse.boltsinternal.Capture) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) JSONObject(org.json.JSONObject) JSONObject(org.json.JSONObject)

Example 8 with Task

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

the class OfflineStore method unpinAsync.

private Task<Void> unpinAsync(final String key, final ParseSQLiteDatabase db) {
    final List<String> uuidsToDelete = new LinkedList<>();
    // A continueWithTask that ends with "return task" is essentially a try-finally.
    return Task.forResult((Void) null).continueWithTask(task -> {
        // Fetch all uuids from Dependencies for key=? grouped by uuid having a
        // count of 1
        String sql = "SELECT " + OfflineSQLiteOpenHelper.KEY_UUID + " FROM " + OfflineSQLiteOpenHelper.TABLE_DEPENDENCIES + " WHERE " + OfflineSQLiteOpenHelper.KEY_KEY + "=? AND " + OfflineSQLiteOpenHelper.KEY_UUID + " IN (" + " SELECT " + OfflineSQLiteOpenHelper.KEY_UUID + " FROM " + OfflineSQLiteOpenHelper.TABLE_DEPENDENCIES + " GROUP BY " + OfflineSQLiteOpenHelper.KEY_UUID + " HAVING COUNT(" + OfflineSQLiteOpenHelper.KEY_UUID + ")=1" + ")";
        String[] args = { key };
        return db.rawQueryAsync(sql, args);
    }).onSuccessTask(task -> {
        // DELETE FROM Objects
        Cursor cursor = task.getResult();
        while (cursor.moveToNext()) {
            uuidsToDelete.add(cursor.getString(0));
        }
        cursor.close();
        return deleteObjects(uuidsToDelete, db);
    }).onSuccessTask(task -> {
        // DELETE FROM Dependencies
        String where = OfflineSQLiteOpenHelper.KEY_KEY + "=?";
        String[] args = { key };
        return db.deleteAsync(OfflineSQLiteOpenHelper.TABLE_DEPENDENCIES, where, args);
    }).onSuccess(task -> {
        synchronized (lock) {
            // Remove uuids from memory
            for (String uuid : uuidsToDelete) {
                ParseObject object = uuidToObjectMap.get(uuid);
                if (object != null) {
                    objectToUuidMap.remove(object);
                    uuidToObjectMap.remove(uuid);
                }
            }
        }
        return null;
    });
}
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) Cursor(android.database.Cursor) LinkedList(java.util.LinkedList)

Example 9 with Task

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

the class Parse method initialize.

static void initialize(Configuration configuration, ParsePlugins parsePlugins) {
    if (isInitialized()) {
        PLog.w(TAG, "Parse is already initialized");
        return;
    }
    // NOTE (richardross): We will need this here, as ParsePlugins uses the return value of
    // isLocalDataStoreEnabled() to perform additional behavior.
    isLocalDatastoreEnabled = configuration.localDataStoreEnabled;
    allowCustomObjectId = configuration.allowCustomObjectId;
    if (parsePlugins == null) {
        ParsePlugins.initialize(configuration.context, configuration);
    } else {
        ParsePlugins.set(parsePlugins);
    }
    try {
        ParseRESTCommand.server = new URL(configuration.server);
    } catch (MalformedURLException ex) {
        throw new RuntimeException(ex);
    }
    ParseObject.registerParseSubclasses();
    if (configuration.localDataStoreEnabled) {
        offlineStore = new OfflineStore(configuration.context);
    } else {
        ParseKeyValueCache.initialize(configuration.context);
    }
    // Make sure the data on disk for Parse is for the current
    // application.
    checkCacheApplicationId();
    final Context context = configuration.context;
    Task.callInBackground((Callable<Void>) () -> {
        getEventuallyQueue(context);
        return null;
    });
    ParseFieldOperations.registerDefaultDecoders();
    if (!allParsePushIntentReceiversInternal()) {
        throw new SecurityException("To prevent external tampering to your app's notifications, " + "all receivers registered to handle the following actions must have " + "their exported attributes set to false: com.parse.push.intent.RECEIVE, " + "com.parse.push.intent.OPEN, com.parse.push.intent.DELETE");
    }
    ParseUser.getCurrentUserAsync().makeVoid().continueWith((Continuation<Void, Void>) task -> {
        ParseConfig.getCurrentConfig();
        return null;
    }, Task.BACKGROUND_EXECUTOR);
    dispatchOnParseInitialized();
    // FYI we probably don't want to do this if we ever add other callbacks.
    synchronized (MUTEX_CALLBACKS) {
        Parse.callbacks = null;
    }
}
Also used : Context(android.content.Context) Context(android.content.Context) RandomAccessFile(java.io.RandomAccessFile) PackageManager(android.content.pm.PackageManager) MalformedURLException(java.net.MalformedURLException) NonNull(androidx.annotation.NonNull) URL(java.net.URL) FileOutputStream(java.io.FileOutputStream) Set(java.util.Set) IOException(java.io.IOException) Callable(java.util.concurrent.Callable) File(java.io.File) ResolveInfo(android.content.pm.ResolveInfo) HashSet(java.util.HashSet) List(java.util.List) Nullable(androidx.annotation.Nullable) Continuation(com.parse.boltsinternal.Continuation) OkHttpClient(okhttp3.OkHttpClient) Task(com.parse.boltsinternal.Task) Log(android.util.Log) MalformedURLException(java.net.MalformedURLException) URL(java.net.URL)

Example 10 with Task

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

the class ParseRequest method executeAsync.

private Task<Response> executeAsync(final ParseHttpClient client, final ParseHttpRequest request, final int attemptsMade, final long delay, final ProgressCallback downloadProgressCallback, final Task<Void> cancellationToken) {
    if (cancellationToken != null && cancellationToken.isCancelled()) {
        return Task.cancelled();
    }
    return sendOneRequestAsync(client, request, downloadProgressCallback).continueWithTask(task -> {
        Exception e = task.getError();
        if (task.isFaulted() && e instanceof ParseException) {
            if (cancellationToken != null && cancellationToken.isCancelled()) {
                return Task.cancelled();
            }
            if (e instanceof ParseRequestException && ((ParseRequestException) e).isPermanentFailure) {
                return task;
            }
            if (attemptsMade < maxRetries()) {
                PLog.i("com.parse.ParseRequest", "Request failed. Waiting " + delay + " milliseconds before attempt #" + (attemptsMade + 1));
                final TaskCompletionSource<Response> retryTask = new TaskCompletionSource<>();
                ParseExecutors.scheduled().schedule(() -> {
                    executeAsync(client, request, attemptsMade + 1, delay * 2, downloadProgressCallback, cancellationToken).continueWithTask((Continuation<Response, Task<Void>>) task1 -> {
                        if (task1.isCancelled()) {
                            retryTask.setCancelled();
                        } else if (task1.isFaulted()) {
                            retryTask.setError(task1.getError());
                        } else {
                            retryTask.setResult(task1.getResult());
                        }
                        return null;
                    });
                }, delay, TimeUnit.MILLISECONDS);
                return retryTask.getTask();
            }
        }
        return task;
    });
}
Also used : ParseHttpResponse(com.parse.http.ParseHttpResponse) ParseHttpRequest(com.parse.http.ParseHttpRequest) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor) NonNull(androidx.annotation.NonNull) IOException(java.io.IOException) BlockingQueue(java.util.concurrent.BlockingQueue) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) TimeUnit(java.util.concurrent.TimeUnit) ParseHttpBody(com.parse.http.ParseHttpBody) Continuation(com.parse.boltsinternal.Continuation) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ThreadFactory(java.util.concurrent.ThreadFactory) Task(com.parse.boltsinternal.Task) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) ParseHttpResponse(com.parse.http.ParseHttpResponse) ExecutorService(java.util.concurrent.ExecutorService) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) Task(com.parse.boltsinternal.Task) IOException(java.io.IOException)

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