16772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru/*
26772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * Copyright (C) 2011 The Android Open Source Project
36772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *
46772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * Licensed under the Apache License, Version 2.0 (the "License");
56772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * you may not use this file except in compliance with the License.
66772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * You may obtain a copy of the License at
76772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *
86772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *      http://www.apache.org/licenses/LICENSE-2.0
96772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *
106772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * Unless required by applicable law or agreed to in writing, software
116772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * distributed under the License is distributed on an "AS IS" BASIS,
126772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * See the License for the specific language governing permissions and
146772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * limitations under the License.
156772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru */
166772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
176772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Querupackage com.android.volley.toolbox;
186772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
196772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queruimport com.android.volley.Request;
206772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queruimport com.android.volley.Response;
216772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queruimport com.android.volley.VolleyError;
226772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
236772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queruimport java.util.concurrent.ExecutionException;
246772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queruimport java.util.concurrent.Future;
256772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queruimport java.util.concurrent.TimeUnit;
266772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queruimport java.util.concurrent.TimeoutException;
276772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
286772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru/**
296772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * A Future that represents a Volley request.
306772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *
316772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * Used by providing as your response and error listeners. For example:
326772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * <pre>
336772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * RequestFuture&lt;JSONObject&gt; future = RequestFuture.newFuture();
346772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * MyRequest request = new MyRequest(URL, future, future);
356772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *
366772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * // If you want to be able to cancel the request:
376772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * future.setRequest(requestQueue.add(request));
386772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *
396772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * // Otherwise:
406772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * requestQueue.add(request);
416772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *
426772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * try {
436772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *   JSONObject response = future.get();
446772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *   // do something with response
456772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * } catch (InterruptedException e) {
466772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *   // handle the error
476772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * } catch (ExecutionException e) {
486772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *   // handle the error
496772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * }
506772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * </pre>
516772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru *
526772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru * @param <T> The type of parsed response this future expects.
536772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru */
546772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Querupublic class RequestFuture<T> implements Future<T>, Response.Listener<T>,
556772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru       Response.ErrorListener {
566772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    private Request<?> mRequest;
576772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    private boolean mResultReceived = false;
586772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    private T mResult;
596772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    private VolleyError mException;
606772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
616772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    public static <E> RequestFuture<E> newFuture() {
626772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        return new RequestFuture<E>();
636772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    }
646772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
656772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    private RequestFuture() {}
666772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
676772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    public void setRequest(Request<?> request) {
686772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        mRequest = request;
696772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    }
706772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
716772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    @Override
726772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    public synchronized boolean cancel(boolean mayInterruptIfRunning) {
736772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        if (mRequest == null) {
746772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            return false;
756772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        }
766772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
776772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        if (!isDone()) {
786772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            mRequest.cancel();
796772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            return true;
806772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        } else {
816772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            return false;
826772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        }
836772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    }
846772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
856772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    @Override
866772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    public T get() throws InterruptedException, ExecutionException {
876772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        try {
886772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            return doGet(null);
896772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        } catch (TimeoutException e) {
906772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            throw new AssertionError(e);
916772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        }
926772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    }
936772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
946772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    @Override
956772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    public T get(long timeout, TimeUnit unit)
966772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            throws InterruptedException, ExecutionException, TimeoutException {
976772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        return doGet(TimeUnit.MILLISECONDS.convert(timeout, unit));
986772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    }
996772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
1006772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    private synchronized T doGet(Long timeoutMs)
1016772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            throws InterruptedException, ExecutionException, TimeoutException {
1026772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        if (mException != null) {
1036772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            throw new ExecutionException(mException);
1046772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        }
1056772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
1066772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        if (mResultReceived) {
1076772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            return mResult;
1086772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        }
1096772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
1106772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        if (timeoutMs == null) {
1116772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            wait(0);
1126772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        } else if (timeoutMs > 0) {
1136772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            wait(timeoutMs);
1146772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        }
1156772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
1166772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        if (mException != null) {
1176772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            throw new ExecutionException(mException);
1186772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        }
1196772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
1206772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        if (!mResultReceived) {
1216772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            throw new TimeoutException();
1226772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        }
1236772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
1246772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        return mResult;
1256772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    }
1266772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
1276772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    @Override
1286772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    public boolean isCancelled() {
1296772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        if (mRequest == null) {
1306772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru            return false;
1316772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        }
1326772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        return mRequest.isCanceled();
1336772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    }
1346772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
1356772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    @Override
1366772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    public synchronized boolean isDone() {
1376772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        return mResultReceived || mException != null || isCancelled();
1386772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    }
1396772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
1406772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    @Override
1416772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    public synchronized void onResponse(T response) {
1426772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        mResultReceived = true;
1436772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        mResult = response;
1446772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        notifyAll();
1456772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    }
1466772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
1476772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    @Override
1486772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    public synchronized void onErrorResponse(VolleyError error) {
1496772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        mException = error;
1506772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru        notifyAll();
1516772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru    }
1526772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru}
1536772bce3d3322ccbcf6481545ffe895d5d401b39Jean-Baptiste Queru
154