1b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick/*
2b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * Copyright (C) 2011 The Android Open Source Project
3b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *
4b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * Licensed under the Apache License, Version 2.0 (the "License");
5b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * you may not use this file except in compliance with the License.
6b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * You may obtain a copy of the License at
7b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *
8b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *      http://www.apache.org/licenses/LICENSE-2.0
9b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *
10b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * Unless required by applicable law or agreed to in writing, software
11b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * distributed under the License is distributed on an "AS IS" BASIS,
12b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * See the License for the specific language governing permissions and
14b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * limitations under the License.
15b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick */
16b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
17b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrickpackage com.android.volley.toolbox;
18b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
19b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrickimport com.android.volley.Request;
20b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrickimport com.android.volley.Response;
21b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrickimport com.android.volley.VolleyError;
22b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
23b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrickimport java.util.concurrent.ExecutionException;
24b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrickimport java.util.concurrent.Future;
25b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrickimport java.util.concurrent.TimeUnit;
26b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrickimport java.util.concurrent.TimeoutException;
27b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
28b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick/**
29b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * A Future that represents a Volley request.
30b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *
31b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * Used by providing as your response and error listeners. For example:
32b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * <pre>
33b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * RequestFuture&lt;JSONObject&gt; future = RequestFuture.newFuture();
34b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * MyRequest request = new MyRequest(URL, future, future);
35b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *
36b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * // If you want to be able to cancel the request:
37b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * future.setRequest(requestQueue.add(request));
38b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *
39b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * // Otherwise:
40b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * requestQueue.add(request);
41b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *
42b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * try {
43b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *   JSONObject response = future.get();
44b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *   // do something with response
45b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * } catch (InterruptedException e) {
46b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *   // handle the error
47b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * } catch (ExecutionException e) {
48b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *   // handle the error
49b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * }
50b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * </pre>
51b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick *
52b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick * @param <T> The type of parsed response this future expects.
53b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick */
54b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrickpublic class RequestFuture<T> implements Future<T>, Response.Listener<T>,
55b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick       Response.ErrorListener {
56b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    private Request<?> mRequest;
57b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    private boolean mResultReceived = false;
58b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    private T mResult;
59b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    private VolleyError mException;
60b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
61b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    public static <E> RequestFuture<E> newFuture() {
62b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        return new RequestFuture<E>();
63b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    }
64b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
65b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    private RequestFuture() {}
66b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
67b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    public void setRequest(Request<?> request) {
68b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        mRequest = request;
69b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    }
70b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
71b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    @Override
72b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    public synchronized boolean cancel(boolean mayInterruptIfRunning) {
73b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        if (mRequest == null) {
74b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            return false;
75b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        }
76b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
77b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        if (!isDone()) {
78b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            mRequest.cancel();
79b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            return true;
80b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        } else {
81b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            return false;
82b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        }
83b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    }
84b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
85b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    @Override
86b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    public T get() throws InterruptedException, ExecutionException {
87b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        try {
88b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            return doGet(null);
89b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        } catch (TimeoutException e) {
90b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            throw new AssertionError(e);
91b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        }
92b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    }
93b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
94b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    @Override
95b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    public T get(long timeout, TimeUnit unit)
96b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            throws InterruptedException, ExecutionException, TimeoutException {
97b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        return doGet(TimeUnit.MILLISECONDS.convert(timeout, unit));
98b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    }
99b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
100b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    private synchronized T doGet(Long timeoutMs)
101b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            throws InterruptedException, ExecutionException, TimeoutException {
102b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        if (mException != null) {
103b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            throw new ExecutionException(mException);
104b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        }
105b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
106b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        if (mResultReceived) {
107b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            return mResult;
108b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        }
109b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
110b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        if (timeoutMs == null) {
111b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            wait(0);
112b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        } else if (timeoutMs > 0) {
113b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            wait(timeoutMs);
114b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        }
115b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
116b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        if (mException != null) {
117b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            throw new ExecutionException(mException);
118b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        }
119b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
120b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        if (!mResultReceived) {
121b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            throw new TimeoutException();
122b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        }
123b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
124b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        return mResult;
125b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    }
126b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
127b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    @Override
128b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    public boolean isCancelled() {
129b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        if (mRequest == null) {
130b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick            return false;
131b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        }
132b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        return mRequest.isCanceled();
133b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    }
134b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
135b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    @Override
136b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    public synchronized boolean isDone() {
137b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        return mResultReceived || mException != null || isCancelled();
138b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    }
139b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
140b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    @Override
141b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    public synchronized void onResponse(T response) {
142b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        mResultReceived = true;
143b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        mResult = response;
144b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        notifyAll();
145b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    }
146b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
147b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    @Override
148b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    public synchronized void onErrorResponse(VolleyError error) {
149b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        mException = error;
150b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick        notifyAll();
151b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick    }
152b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick}
153b5f1a5083f4d6a0e4ca8403243b37ea2609bcf39Ficus Kirkpatrick
154