aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/android/volley/Cache.java14
-rw-r--r--src/main/java/com/android/volley/CacheDispatcher.java1
-rw-r--r--src/main/java/com/android/volley/Network.java2
-rw-r--r--src/main/java/com/android/volley/RequestQueue.java28
-rw-r--r--src/main/java/com/android/volley/Response.java4
-rw-r--r--src/main/java/com/android/volley/ResponseDelivery.java6
-rw-r--r--src/main/java/com/android/volley/RetryPolicy.java6
-rw-r--r--src/main/java/com/android/volley/VolleyLog.java8
-rw-r--r--src/main/java/com/android/volley/toolbox/Authenticator.java4
-rw-r--r--src/main/java/com/android/volley/toolbox/BasicNetwork.java8
-rw-r--r--src/main/java/com/android/volley/toolbox/ByteArrayPool.java4
-rw-r--r--src/main/java/com/android/volley/toolbox/DiskBasedCache.java225
-rw-r--r--src/main/java/com/android/volley/toolbox/HttpHeaderParser.java2
-rw-r--r--src/main/java/com/android/volley/toolbox/HttpStack.java2
-rw-r--r--src/main/java/com/android/volley/toolbox/HurlStack.java30
-rw-r--r--src/main/java/com/android/volley/toolbox/ImageLoader.java6
-rw-r--r--src/main/java/com/android/volley/toolbox/ImageRequest.java6
-rw-r--r--src/main/java/com/android/volley/toolbox/JsonRequest.java4
-rw-r--r--src/main/java/com/android/volley/toolbox/NetworkImageView.java7
-rw-r--r--src/main/java/com/android/volley/toolbox/StringRequest.java4
20 files changed, 201 insertions, 170 deletions
diff --git a/src/main/java/com/android/volley/Cache.java b/src/main/java/com/android/volley/Cache.java
index f1ec757..8482c22 100644
--- a/src/main/java/com/android/volley/Cache.java
+++ b/src/main/java/com/android/volley/Cache.java
@@ -28,43 +28,43 @@ public interface Cache {
* @param key Cache key
* @return An {@link Entry} or null in the event of a cache miss
*/
- public Entry get(String key);
+ Entry get(String key);
/**
* Adds or replaces an entry to the cache.
* @param key Cache key
* @param entry Data to store and metadata for cache coherency, TTL, etc.
*/
- public void put(String key, Entry entry);
+ void put(String key, Entry entry);
/**
* Performs any potentially long-running actions needed to initialize the cache;
* will be called from a worker thread.
*/
- public void initialize();
+ void initialize();
/**
* Invalidates an entry in the cache.
* @param key Cache key
* @param fullExpire True to fully expire the entry, false to soft expire
*/
- public void invalidate(String key, boolean fullExpire);
+ void invalidate(String key, boolean fullExpire);
/**
* Removes an entry from the cache.
* @param key Cache key
*/
- public void remove(String key);
+ void remove(String key);
/**
* Empties the cache.
*/
- public void clear();
+ void clear();
/**
* Data and metadata for an entry returned by the cache.
*/
- public static class Entry {
+ class Entry {
/** The data returned from cache. */
public byte[] data;
diff --git a/src/main/java/com/android/volley/CacheDispatcher.java b/src/main/java/com/android/volley/CacheDispatcher.java
index 18d219b..1e7dfc4 100644
--- a/src/main/java/com/android/volley/CacheDispatcher.java
+++ b/src/main/java/com/android/volley/CacheDispatcher.java
@@ -151,7 +151,6 @@ public class CacheDispatcher extends Thread {
if (mQuit) {
return;
}
- continue;
}
}
}
diff --git a/src/main/java/com/android/volley/Network.java b/src/main/java/com/android/volley/Network.java
index ab45830..1e367c8 100644
--- a/src/main/java/com/android/volley/Network.java
+++ b/src/main/java/com/android/volley/Network.java
@@ -26,5 +26,5 @@ public interface Network {
* @return A {@link NetworkResponse} with data and caching metadata; will never be null
* @throws VolleyError on errors
*/
- public NetworkResponse performRequest(Request<?> request) throws VolleyError;
+ NetworkResponse performRequest(Request<?> request) throws VolleyError;
}
diff --git a/src/main/java/com/android/volley/RequestQueue.java b/src/main/java/com/android/volley/RequestQueue.java
index 4324590..0f2e756 100644
--- a/src/main/java/com/android/volley/RequestQueue.java
+++ b/src/main/java/com/android/volley/RequestQueue.java
@@ -40,13 +40,13 @@ import java.util.concurrent.atomic.AtomicInteger;
public class RequestQueue {
/** Callback interface for completed requests. */
- public static interface RequestFinishedListener<T> {
+ public interface RequestFinishedListener<T> {
/** Called when a request has finished processing. */
- public void onRequestFinished(Request<T> request);
+ void onRequestFinished(Request<T> request);
}
/** Used for generating monotonically-increasing sequence numbers for requests. */
- private AtomicInteger mSequenceGenerator = new AtomicInteger();
+ private final AtomicInteger mSequenceGenerator = new AtomicInteger();
/**
* Staging area for requests that already have a duplicate request in flight.
@@ -59,7 +59,7 @@ public class RequestQueue {
* </ul>
*/
private final Map<String, Queue<Request<?>>> mWaitingRequests =
- new HashMap<String, Queue<Request<?>>>();
+ new HashMap<>();
/**
* The set of all requests currently being processed by this RequestQueue. A Request
@@ -70,11 +70,11 @@ public class RequestQueue {
/** The cache triage queue. */
private final PriorityBlockingQueue<Request<?>> mCacheQueue =
- new PriorityBlockingQueue<Request<?>>();
+ new PriorityBlockingQueue<>();
/** The queue of requests that are actually going out to the network. */
private final PriorityBlockingQueue<Request<?>> mNetworkQueue =
- new PriorityBlockingQueue<Request<?>>();
+ new PriorityBlockingQueue<>();
/** Number of network request dispatcher threads to start. */
private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;
@@ -89,13 +89,13 @@ public class RequestQueue {
private final ResponseDelivery mDelivery;
/** The network dispatchers. */
- private NetworkDispatcher[] mDispatchers;
+ private final NetworkDispatcher[] mDispatchers;
/** The cache dispatcher. */
private CacheDispatcher mCacheDispatcher;
- private List<RequestFinishedListener> mFinishedListeners =
- new ArrayList<RequestFinishedListener>();
+ private final List<RequestFinishedListener> mFinishedListeners =
+ new ArrayList<>();
/**
* Creates the worker pool. Processing will not begin until {@link #start()} is called.
@@ -160,9 +160,9 @@ public class RequestQueue {
if (mCacheDispatcher != null) {
mCacheDispatcher.quit();
}
- for (int i = 0; i < mDispatchers.length; i++) {
- if (mDispatchers[i] != null) {
- mDispatchers[i].quit();
+ for (final NetworkDispatcher mDispatcher : mDispatchers) {
+ if (mDispatcher != null) {
+ mDispatcher.quit();
}
}
}
@@ -186,7 +186,7 @@ public class RequestQueue {
* {@link RequestQueue#cancelAll(RequestFilter)}.
*/
public interface RequestFilter {
- public boolean apply(Request<?> request);
+ boolean apply(Request<?> request);
}
/**
@@ -248,7 +248,7 @@ public class RequestQueue {
// There is already a request in flight. Queue up.
Queue<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey);
if (stagedRequests == null) {
- stagedRequests = new LinkedList<Request<?>>();
+ stagedRequests = new LinkedList<>();
}
stagedRequests.add(request);
mWaitingRequests.put(cacheKey, stagedRequests);
diff --git a/src/main/java/com/android/volley/Response.java b/src/main/java/com/android/volley/Response.java
index 1165595..1fe7215 100644
--- a/src/main/java/com/android/volley/Response.java
+++ b/src/main/java/com/android/volley/Response.java
@@ -26,7 +26,7 @@ public class Response<T> {
/** Callback interface for delivering parsed responses. */
public interface Listener<T> {
/** Called when a response is received. */
- public void onResponse(T response);
+ void onResponse(T response);
}
/** Callback interface for delivering error responses. */
@@ -35,7 +35,7 @@ public class Response<T> {
* Callback method that an error has been occurred with the
* provided error code and optional user-readable message.
*/
- public void onErrorResponse(VolleyError error);
+ void onErrorResponse(VolleyError error);
}
/** Returns a successful response containing the parsed result. */
diff --git a/src/main/java/com/android/volley/ResponseDelivery.java b/src/main/java/com/android/volley/ResponseDelivery.java
index 87706af..bef3df5 100644
--- a/src/main/java/com/android/volley/ResponseDelivery.java
+++ b/src/main/java/com/android/volley/ResponseDelivery.java
@@ -20,16 +20,16 @@ public interface ResponseDelivery {
/**
* Parses a response from the network or cache and delivers it.
*/
- public void postResponse(Request<?> request, Response<?> response);
+ void postResponse(Request<?> request, Response<?> response);
/**
* Parses a response from the network or cache and delivers it. The provided
* Runnable will be executed after delivery.
*/
- public void postResponse(Request<?> request, Response<?> response, Runnable runnable);
+ void postResponse(Request<?> request, Response<?> response, Runnable runnable);
/**
* Posts an error for the given request.
*/
- public void postError(Request<?> request, VolleyError error);
+ void postError(Request<?> request, VolleyError error);
}
diff --git a/src/main/java/com/android/volley/RetryPolicy.java b/src/main/java/com/android/volley/RetryPolicy.java
index 0dd198b..f58678d 100644
--- a/src/main/java/com/android/volley/RetryPolicy.java
+++ b/src/main/java/com/android/volley/RetryPolicy.java
@@ -24,12 +24,12 @@ public interface RetryPolicy {
/**
* Returns the current timeout (used for logging).
*/
- public int getCurrentTimeout();
+ int getCurrentTimeout();
/**
* Returns the current retry count (used for logging).
*/
- public int getCurrentRetryCount();
+ int getCurrentRetryCount();
/**
* Prepares for the next retry by applying a backoff to the timeout.
@@ -37,5 +37,5 @@ public interface RetryPolicy {
* @throws VolleyError In the event that the retry could not be performed (for example if we
* ran out of attempts), the passed in error is thrown.
*/
- public void retry(VolleyError error) throws VolleyError;
+ void retry(VolleyError error) throws VolleyError;
}
diff --git a/src/main/java/com/android/volley/VolleyLog.java b/src/main/java/com/android/volley/VolleyLog.java
index ffe9eb8..fc776e5 100644
--- a/src/main/java/com/android/volley/VolleyLog.java
+++ b/src/main/java/com/android/volley/VolleyLog.java
@@ -25,8 +25,8 @@ import java.util.Locale;
/**
* Logging helper class.
- * <p/>
- * to see Volley logs call:<br/>
+ * <p>
+ * to see Volley logs call:<br>
* {@code <android-sdk>/platform-tools/adb shell setprop log.tag.Volley VERBOSE}
*/
public class VolleyLog {
@@ -37,9 +37,9 @@ public class VolleyLog {
/**
* Customize the log tag for your application, so that other apps
* using Volley don't mix their logs with yours.
- * <br />
+ * <br>
* Enable the log property for your tag before starting your app:
- * <br />
+ * <br>
* {@code adb shell setprop log.tag.&lt;tag&gt;}
*/
public static void setTag(String tag) {
diff --git a/src/main/java/com/android/volley/toolbox/Authenticator.java b/src/main/java/com/android/volley/toolbox/Authenticator.java
index d9f5e3c..adfc996 100644
--- a/src/main/java/com/android/volley/toolbox/Authenticator.java
+++ b/src/main/java/com/android/volley/toolbox/Authenticator.java
@@ -27,10 +27,10 @@ public interface Authenticator {
*
* @throws AuthFailureError If authentication did not succeed
*/
- public String getAuthToken() throws AuthFailureError;
+ String getAuthToken() throws AuthFailureError;
/**
* Invalidates the provided auth token.
*/
- public void invalidateAuthToken(String authToken);
+ void invalidateAuthToken(String authToken);
}
diff --git a/src/main/java/com/android/volley/toolbox/BasicNetwork.java b/src/main/java/com/android/volley/toolbox/BasicNetwork.java
index 37c35ec..96fb66e 100644
--- a/src/main/java/com/android/volley/toolbox/BasicNetwork.java
+++ b/src/main/java/com/android/volley/toolbox/BasicNetwork.java
@@ -57,9 +57,9 @@ import java.util.TreeMap;
public class BasicNetwork implements Network {
protected static final boolean DEBUG = VolleyLog.DEBUG;
- private static int SLOW_REQUEST_THRESHOLD_MS = 3000;
+ private static final int SLOW_REQUEST_THRESHOLD_MS = 3000;
- private static int DEFAULT_POOL_SIZE = 4096;
+ private static final int DEFAULT_POOL_SIZE = 4096;
protected final HttpStack mHttpStack;
@@ -257,7 +257,7 @@ public class BasicNetwork implements Network {
} catch (IOException e) {
// This can happen if there was an exception above that left the entity in
// an invalid state.
- VolleyLog.v("Error occured when calling consumingContent");
+ VolleyLog.v("Error occurred when calling consumingContent");
}
mPool.returnBuf(buffer);
bytes.close();
@@ -265,7 +265,7 @@ public class BasicNetwork implements Network {
}
/**
- * Converts Headers[] to Map<String, String>.
+ * Converts Headers[] to Map&lt;String, String&gt;.
*/
protected static Map<String, String> convertHeaders(Header[] headers) {
Map<String, String> result = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
diff --git a/src/main/java/com/android/volley/toolbox/ByteArrayPool.java b/src/main/java/com/android/volley/toolbox/ByteArrayPool.java
index af95076..c8ca2c2 100644
--- a/src/main/java/com/android/volley/toolbox/ByteArrayPool.java
+++ b/src/main/java/com/android/volley/toolbox/ByteArrayPool.java
@@ -53,8 +53,8 @@ import java.util.List;
*/
public class ByteArrayPool {
/** The buffer pool, arranged both by last use and by buffer size */
- private List<byte[]> mBuffersByLastUse = new LinkedList<byte[]>();
- private List<byte[]> mBuffersBySize = new ArrayList<byte[]>(64);
+ private final List<byte[]> mBuffersByLastUse = new LinkedList<byte[]>();
+ private final List<byte[]> mBuffersBySize = new ArrayList<byte[]>(64);
/** The total size of the buffers in the pool */
private int mCurrentSize = 0;
diff --git a/src/main/java/com/android/volley/toolbox/DiskBasedCache.java b/src/main/java/com/android/volley/toolbox/DiskBasedCache.java
index f724d72..0e65183 100644
--- a/src/main/java/com/android/volley/toolbox/DiskBasedCache.java
+++ b/src/main/java/com/android/volley/toolbox/DiskBasedCache.java
@@ -17,15 +17,18 @@
package com.android.volley.toolbox;
import android.os.SystemClock;
+import android.text.TextUtils;
import com.android.volley.Cache;
import com.android.volley.VolleyLog;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
@@ -110,30 +113,31 @@ public class DiskBasedCache implements Cache {
if (entry == null) {
return null;
}
-
File file = getFileForKey(key);
- CountingInputStream cis = null;
try {
- cis = new CountingInputStream(new BufferedInputStream(new FileInputStream(file)));
- CacheHeader.readHeader(cis); // eat header
- byte[] data = streamToBytes(cis, (int) (file.length() - cis.bytesRead));
- return entry.toCacheEntry(data);
+ CountingInputStream cis = new CountingInputStream(
+ new BufferedInputStream(createInputStream(file)), file.length());
+ try {
+ CacheHeader entryOnDisk = CacheHeader.readHeader(cis);
+ if (!TextUtils.equals(key, entryOnDisk.key)) {
+ // File was shared by two keys and now holds data for a different entry!
+ VolleyLog.d("%s: key=%s, found=%s",
+ file.getAbsolutePath(), key, entryOnDisk.key);
+ // Remove key whose contents on disk have been replaced.
+ removeEntry(key);
+ return null;
+ }
+ byte[] data = streamToBytes(cis, cis.bytesRemaining());
+ return entry.toCacheEntry(data);
+ } finally {
+ // Any IOException thrown here is handled by the below catch block by design.
+ //noinspection ThrowFromFinallyBlock
+ cis.close();
+ }
} catch (IOException e) {
VolleyLog.d("%s: %s", file.getAbsolutePath(), e.toString());
remove(key);
return null;
- } catch (NegativeArraySizeException e) {
- VolleyLog.d("%s: %s", file.getAbsolutePath(), e.toString());
- remove(key);
- return null;
- } finally {
- if (cis != null) {
- try {
- cis.close();
- } catch (IOException ioe) {
- return null;
- }
- }
}
}
@@ -149,28 +153,29 @@ public class DiskBasedCache implements Cache {
}
return;
}
-
File[] files = mRootDirectory.listFiles();
if (files == null) {
return;
}
for (File file : files) {
- BufferedInputStream fis = null;
try {
- fis = new BufferedInputStream(new FileInputStream(file));
- CacheHeader entry = CacheHeader.readHeader(fis);
- entry.size = file.length();
- putEntry(entry.key, entry);
- } catch (IOException e) {
- if (file != null) {
- file.delete();
- }
- } finally {
+ long entrySize = file.length();
+ CountingInputStream cis = new CountingInputStream(
+ new BufferedInputStream(createInputStream(file)), entrySize);
try {
- if (fis != null) {
- fis.close();
- }
- } catch (IOException ignored) { }
+ CacheHeader entry = CacheHeader.readHeader(cis);
+ // NOTE: When this entry was put, its size was recorded as data.length, but
+ // when the entry is initialized below, its size is recorded as file.length()
+ entry.size = entrySize;
+ putEntry(entry.key, entry);
+ } finally {
+ // Any IOException thrown here is handled by the below catch block by design.
+ //noinspection ThrowFromFinallyBlock
+ cis.close();
+ }
+ } catch (IOException e) {
+ //noinspection ResultOfMethodCallIgnored
+ file.delete();
}
}
}
@@ -190,7 +195,6 @@ public class DiskBasedCache implements Cache {
}
put(key, entry);
}
-
}
/**
@@ -201,7 +205,7 @@ public class DiskBasedCache implements Cache {
pruneIfNeeded(entry.data.length);
File file = getFileForKey(key);
try {
- BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(file));
+ BufferedOutputStream fos = new BufferedOutputStream(createOutputStream(file));
CacheHeader e = new CacheHeader(key, entry);
boolean success = e.writeHeader(fos);
if (!success) {
@@ -313,107 +317,118 @@ public class DiskBasedCache implements Cache {
* Removes the entry identified by 'key' from the cache.
*/
private void removeEntry(String key) {
- CacheHeader entry = mEntries.get(key);
- if (entry != null) {
- mTotalSize -= entry.size;
- mEntries.remove(key);
+ CacheHeader removed = mEntries.remove(key);
+ if (removed != null) {
+ mTotalSize -= removed.size;
}
}
/**
- * Reads the contents of an InputStream into a byte[].
- * */
- private static byte[] streamToBytes(InputStream in, int length) throws IOException {
- byte[] bytes = new byte[length];
- int count;
- int pos = 0;
- while (pos < length && ((count = in.read(bytes, pos, length - pos)) != -1)) {
- pos += count;
- }
- if (pos != length) {
- throw new IOException("Expected " + length + " bytes, read " + pos + " bytes");
+ * Reads length bytes from CountingInputStream into byte array.
+ * @param cis input stream
+ * @param length number of bytes to read
+ * @throws IOException if fails to read all bytes
+ */
+ //VisibleForTesting
+ static byte[] streamToBytes(CountingInputStream cis, long length) throws IOException {
+ long maxLength = cis.bytesRemaining();
+ // Length cannot be negative or greater than bytes remaining, and must not overflow int.
+ if (length < 0 || length > maxLength || (int) length != length) {
+ throw new IOException("streamToBytes length=" + length + ", maxLength=" + maxLength);
}
+ byte[] bytes = new byte[(int) length];
+ new DataInputStream(cis).readFully(bytes);
return bytes;
}
+ //VisibleForTesting
+ InputStream createInputStream(File file) throws FileNotFoundException {
+ return new FileInputStream(file);
+ }
+
+ //VisibleForTesting
+ OutputStream createOutputStream(File file) throws FileNotFoundException {
+ return new FileOutputStream(file);
+ }
+
/**
* Handles holding onto the cache headers for an entry.
*/
- // Visible for testing.
+ //VisibleForTesting
static class CacheHeader {
/** The size of the data identified by this CacheHeader. (This is not
* serialized to disk. */
- public long size;
+ long size;
/** The key that identifies the cache entry. */
- public String key;
+ final String key;
/** ETag for cache coherence. */
- public String etag;
+ final String etag;
/** Date of this response as reported by the server. */
- public long serverDate;
+ final long serverDate;
/** The last modified date for the requested object. */
- public long lastModified;
+ final long lastModified;
/** TTL for this record. */
- public long ttl;
+ final long ttl;
/** Soft TTL for this record. */
- public long softTtl;
+ final long softTtl;
/** Headers from the response resulting in this cache entry. */
- public Map<String, String> responseHeaders;
+ final Map<String, String> responseHeaders;
- private CacheHeader() { }
+ private CacheHeader(String key, String etag, long serverDate, long lastModified, long ttl,
+ long softTtl, Map<String, String> responseHeaders) {
+ this.key = key;
+ this.etag = ("".equals(etag)) ? null : etag;
+ this.serverDate = serverDate;
+ this.lastModified = lastModified;
+ this.ttl = ttl;
+ this.softTtl = softTtl;
+ this.responseHeaders = responseHeaders;
+ }
/**
* Instantiates a new CacheHeader object
* @param key The key that identifies the cache entry
* @param entry The cache entry.
*/
- public CacheHeader(String key, Entry entry) {
- this.key = key;
- this.size = entry.data.length;
- this.etag = entry.etag;
- this.serverDate = entry.serverDate;
- this.lastModified = entry.lastModified;
- this.ttl = entry.ttl;
- this.softTtl = entry.softTtl;
- this.responseHeaders = entry.responseHeaders;
+ CacheHeader(String key, Entry entry) {
+ this(key, entry.etag, entry.serverDate, entry.lastModified, entry.ttl, entry.softTtl,
+ entry.responseHeaders);
+ size = entry.data.length;
}
/**
- * Reads the header off of an InputStream and returns a CacheHeader object.
+ * Reads the header from a CountingInputStream and returns a CacheHeader object.
* @param is The InputStream to read from.
- * @throws IOException
+ * @throws IOException if fails to read header
*/
- public static CacheHeader readHeader(InputStream is) throws IOException {
- CacheHeader entry = new CacheHeader();
+ static CacheHeader readHeader(CountingInputStream is) throws IOException {
int magic = readInt(is);
if (magic != CACHE_MAGIC) {
// don't bother deleting, it'll get pruned eventually
throw new IOException();
}
- entry.key = readString(is);
- entry.etag = readString(is);
- if (entry.etag.equals("")) {
- entry.etag = null;
- }
- entry.serverDate = readLong(is);
- entry.lastModified = readLong(is);
- entry.ttl = readLong(is);
- entry.softTtl = readLong(is);
- entry.responseHeaders = readStringStringMap(is);
-
- return entry;
+ String key = readString(is);
+ String etag = readString(is);
+ long serverDate = readLong(is);
+ long lastModified = readLong(is);
+ long ttl = readLong(is);
+ long softTtl = readLong(is);
+ Map<String, String> responseHeaders = readStringStringMap(is);
+ return new CacheHeader(
+ key, etag, serverDate, lastModified, ttl, softTtl, responseHeaders);
}
/**
* Creates a cache entry for the specified data.
*/
- public Entry toCacheEntry(byte[] data) {
+ Entry toCacheEntry(byte[] data) {
Entry e = new Entry();
e.data = data;
e.etag = etag;
@@ -429,7 +444,7 @@ public class DiskBasedCache implements Cache {
/**
* Writes the contents of this CacheHeader to the specified OutputStream.
*/
- public boolean writeHeader(OutputStream os) {
+ boolean writeHeader(OutputStream os) {
try {
writeInt(os, CACHE_MAGIC);
writeString(os, key);
@@ -446,14 +461,16 @@ public class DiskBasedCache implements Cache {
return false;
}
}
-
}
- private static class CountingInputStream extends FilterInputStream {
- private int bytesRead = 0;
+ //VisibleForTesting
+ static class CountingInputStream extends FilterInputStream {
+ private final long length;
+ private long bytesRead;
- private CountingInputStream(InputStream in) {
+ CountingInputStream(InputStream in, long length) {
super(in);
+ this.length = length;
}
@Override
@@ -473,6 +490,15 @@ public class DiskBasedCache implements Cache {
}
return result;
}
+
+ //VisibleForTesting
+ long bytesRead() {
+ return bytesRead;
+ }
+
+ long bytesRemaining() {
+ return length - bytesRead;
+ }
}
/*
@@ -480,6 +506,8 @@ public class DiskBasedCache implements Cache {
* headers on disk. Once upon a time, this used the standard Java
* Object{Input,Output}Stream, but the default implementation relies heavily
* on reflection (even for standard types) and generates a ton of garbage.
+ *
+ * TODO: Replace by standard DataInput and DataOutput in next cache version.
*/
/**
@@ -540,9 +568,9 @@ public class DiskBasedCache implements Cache {
os.write(b, 0, b.length);
}
- static String readString(InputStream is) throws IOException {
- int n = (int) readLong(is);
- byte[] b = streamToBytes(is, n);
+ static String readString(CountingInputStream cis) throws IOException {
+ long n = readLong(cis);
+ byte[] b = streamToBytes(cis, n);
return new String(b, "UTF-8");
}
@@ -558,18 +586,17 @@ public class DiskBasedCache implements Cache {
}
}
- static Map<String, String> readStringStringMap(InputStream is) throws IOException {
- int size = readInt(is);
+ static Map<String, String> readStringStringMap(CountingInputStream cis) throws IOException {
+ int size = readInt(cis);
Map<String, String> result = (size == 0)
? Collections.<String, String>emptyMap()
: new HashMap<String, String>(size);
for (int i = 0; i < size; i++) {
- String key = readString(is).intern();
- String value = readString(is).intern();
+ String key = readString(cis).intern();
+ String value = readString(cis).intern();
result.put(key, value);
}
return result;
}
-
}
diff --git a/src/main/java/com/android/volley/toolbox/HttpHeaderParser.java b/src/main/java/com/android/volley/toolbox/HttpHeaderParser.java
index c3b48d8..f53063c 100644
--- a/src/main/java/com/android/volley/toolbox/HttpHeaderParser.java
+++ b/src/main/java/com/android/volley/toolbox/HttpHeaderParser.java
@@ -31,7 +31,7 @@ import java.util.Map;
public class HttpHeaderParser {
/**
- * Extracts a {@link Cache.Entry} from a {@link NetworkResponse}.
+ * Extracts a {@link com.android.volley.Cache.Entry} from a {@link NetworkResponse}.
*
* @param response The network response to parse headers from
* @return a cache entry for the given response, or null if the response is not cacheable.
diff --git a/src/main/java/com/android/volley/toolbox/HttpStack.java b/src/main/java/com/android/volley/toolbox/HttpStack.java
index a52fd06..06f6017 100644
--- a/src/main/java/com/android/volley/toolbox/HttpStack.java
+++ b/src/main/java/com/android/volley/toolbox/HttpStack.java
@@ -39,7 +39,7 @@ public interface HttpStack {
* {@link Request#getHeaders()}
* @return the HTTP response
*/
- public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
+ HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
throws IOException, AuthFailureError;
}
diff --git a/src/main/java/com/android/volley/toolbox/HurlStack.java b/src/main/java/com/android/volley/toolbox/HurlStack.java
index c53d5e0..66f441d 100644
--- a/src/main/java/com/android/volley/toolbox/HurlStack.java
+++ b/src/main/java/com/android/volley/toolbox/HurlStack.java
@@ -59,7 +59,7 @@ public class HurlStack implements HttpStack {
* Returns a URL to use instead of the provided one, or null to indicate
* this URL should not be used at all.
*/
- public String rewriteUrl(String originalUrl);
+ String rewriteUrl(String originalUrl);
}
private final UrlRewriter mUrlRewriter;
@@ -209,16 +209,8 @@ public class HurlStack implements HttpStack {
// GET. Otherwise, it is assumed that the request is a POST.
byte[] postBody = request.getPostBody();
if (postBody != null) {
- // Prepare output. There is no need to set Content-Length explicitly,
- // since this is handled by HttpURLConnection using the size of the prepared
- // output stream.
- connection.setDoOutput(true);
connection.setRequestMethod("POST");
- connection.addRequestProperty(HEADER_CONTENT_TYPE,
- request.getPostBodyContentType());
- DataOutputStream out = new DataOutputStream(connection.getOutputStream());
- out.write(postBody);
- out.close();
+ addBody(connection, request, postBody);
}
break;
case Method.GET:
@@ -259,11 +251,19 @@ public class HurlStack implements HttpStack {
throws IOException, AuthFailureError {
byte[] body = request.getBody();
if (body != null) {
- connection.setDoOutput(true);
- connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType());
- DataOutputStream out = new DataOutputStream(connection.getOutputStream());
- out.write(body);
- out.close();
+ addBody(connection, request, body);
}
}
+
+ private static void addBody(HttpURLConnection connection, Request<?> request, byte[] body)
+ throws IOException, AuthFailureError {
+ // Prepare output. There is no need to set Content-Length explicitly,
+ // since this is handled by HttpURLConnection using the size of the prepared
+ // output stream.
+ connection.setDoOutput(true);
+ connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType());
+ DataOutputStream out = new DataOutputStream(connection.getOutputStream());
+ out.write(body);
+ out.close();
+ }
}
diff --git a/src/main/java/com/android/volley/toolbox/ImageLoader.java b/src/main/java/com/android/volley/toolbox/ImageLoader.java
index d5305e3..33a119b 100644
--- a/src/main/java/com/android/volley/toolbox/ImageLoader.java
+++ b/src/main/java/com/android/volley/toolbox/ImageLoader.java
@@ -72,8 +72,8 @@ public class ImageLoader {
* must not block. Implementation with an LruCache is recommended.
*/
public interface ImageCache {
- public Bitmap getBitmap(String url);
- public void putBitmap(String url, Bitmap bitmap);
+ Bitmap getBitmap(String url);
+ void putBitmap(String url, Bitmap bitmap);
}
/**
@@ -139,7 +139,7 @@ public class ImageLoader {
* image loading in order to, for example, run an animation to fade in network loaded
* images.
*/
- public void onResponse(ImageContainer response, boolean isImmediate);
+ void onResponse(ImageContainer response, boolean isImmediate);
}
/**
diff --git a/src/main/java/com/android/volley/toolbox/ImageRequest.java b/src/main/java/com/android/volley/toolbox/ImageRequest.java
index d663f5f..0f33cd8 100644
--- a/src/main/java/com/android/volley/toolbox/ImageRequest.java
+++ b/src/main/java/com/android/volley/toolbox/ImageRequest.java
@@ -46,7 +46,7 @@ public class ImageRequest extends Request<Bitmap> {
private final Config mDecodeConfig;
private final int mMaxWidth;
private final int mMaxHeight;
- private ScaleType mScaleType;
+ private final ScaleType mScaleType;
/** Decoding lock so that we don't decode more than one image at a time (to avoid OOM's) */
private static final Object sDecodeLock = new Object();
@@ -216,7 +216,9 @@ public class ImageRequest extends Request<Bitmap> {
@Override
protected void deliverResponse(Bitmap response) {
- mListener.onResponse(response);
+ if (mListener != null) {
+ mListener.onResponse(response);
+ }
}
/**
diff --git a/src/main/java/com/android/volley/toolbox/JsonRequest.java b/src/main/java/com/android/volley/toolbox/JsonRequest.java
index 2d58f40..40877b1 100644
--- a/src/main/java/com/android/volley/toolbox/JsonRequest.java
+++ b/src/main/java/com/android/volley/toolbox/JsonRequest.java
@@ -63,7 +63,9 @@ public abstract class JsonRequest<T> extends Request<T> {
@Override
protected void deliverResponse(T response) {
- mListener.onResponse(response);
+ if (mListener != null) {
+ mListener.onResponse(response);
+ }
}
@Override
diff --git a/src/main/java/com/android/volley/toolbox/NetworkImageView.java b/src/main/java/com/android/volley/toolbox/NetworkImageView.java
index 324dbc0..60e4815 100644
--- a/src/main/java/com/android/volley/toolbox/NetworkImageView.java
+++ b/src/main/java/com/android/volley/toolbox/NetworkImageView.java
@@ -147,7 +147,9 @@ public class NetworkImageView extends ImageView {
// The pre-existing content of this view didn't match the current URL. Load the new image
// from the network.
- ImageContainer newContainer = mImageLoader.get(mUrl,
+
+ // update the ImageContainer to be the new bitmap container.
+ mImageContainer = mImageLoader.get(mUrl,
new ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
@@ -179,9 +181,6 @@ public class NetworkImageView extends ImageView {
}
}
}, maxWidth, maxHeight, scaleType);
-
- // update the ImageContainer to be the new bitmap container.
- mImageContainer = newContainer;
}
private void setDefaultImageOrNull() {
diff --git a/src/main/java/com/android/volley/toolbox/StringRequest.java b/src/main/java/com/android/volley/toolbox/StringRequest.java
index 6b3dfcf..05a62f6 100644
--- a/src/main/java/com/android/volley/toolbox/StringRequest.java
+++ b/src/main/java/com/android/volley/toolbox/StringRequest.java
@@ -57,7 +57,9 @@ public class StringRequest extends Request<String> {
@Override
protected void deliverResponse(String response) {
- mListener.onResponse(response);
+ if (mListener != null) {
+ mListener.onResponse(response);
+ }
}
@Override