aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/android/volley/toolbox/DiskBasedCache.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/android/volley/toolbox/DiskBasedCache.java')
-rw-r--r--src/main/java/com/android/volley/toolbox/DiskBasedCache.java150
1 files changed, 78 insertions, 72 deletions
diff --git a/src/main/java/com/android/volley/toolbox/DiskBasedCache.java b/src/main/java/com/android/volley/toolbox/DiskBasedCache.java
index a6cd960..c49588f 100644
--- a/src/main/java/com/android/volley/toolbox/DiskBasedCache.java
+++ b/src/main/java/com/android/volley/toolbox/DiskBasedCache.java
@@ -17,12 +17,11 @@
package com.android.volley.toolbox;
import android.os.SystemClock;
+import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
-
import com.android.volley.Cache;
import com.android.volley.Header;
import com.android.volley.VolleyLog;
-
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
@@ -43,16 +42,15 @@ import java.util.List;
import java.util.Map;
/**
- * Cache implementation that caches files directly onto the hard disk in the specified
- * directory. The default disk usage size is 5MB, but is configurable.
+ * Cache implementation that caches files directly onto the hard disk in the specified directory.
+ * The default disk usage size is 5MB, but is configurable.
*
* <p>This cache supports the {@link Entry#allResponseHeaders} headers field.
*/
public class DiskBasedCache implements Cache {
/** Map of the Key, CacheHeader pairs */
- private final Map<String, CacheHeader> mEntries =
- new LinkedHashMap<String, CacheHeader>(16, .75f, true);
+ private final Map<String, CacheHeader> mEntries = new LinkedHashMap<>(16, .75f, true);
/** Total amount of space currently used by the cache in bytes. */
private long mTotalSize = 0;
@@ -74,6 +72,7 @@ public class DiskBasedCache implements Cache {
/**
* Constructs an instance of the DiskBasedCache at the specified directory.
+ *
* @param rootDirectory The root directory of the cache.
* @param maxCacheSizeInBytes The maximum size of the cache in bytes.
*/
@@ -83,17 +82,16 @@ public class DiskBasedCache implements Cache {
}
/**
- * Constructs an instance of the DiskBasedCache at the specified directory using
- * the default maximum cache size of 5MB.
+ * Constructs an instance of the DiskBasedCache at the specified directory using the default
+ * maximum cache size of 5MB.
+ *
* @param rootDirectory The root directory of the cache.
*/
public DiskBasedCache(File rootDirectory) {
this(rootDirectory, DEFAULT_DISK_USAGE_BYTES);
}
- /**
- * Clears the cache. Deletes all cached files from disk.
- */
+ /** Clears the cache. Deletes all cached files from disk. */
@Override
public synchronized void clear() {
File[] files = mRootDirectory.listFiles();
@@ -107,9 +105,7 @@ public class DiskBasedCache implements Cache {
VolleyLog.d("Cache cleared.");
}
- /**
- * Returns the cache entry with the specified key if it exists, null otherwise.
- */
+ /** Returns the cache entry with the specified key if it exists, null otherwise. */
@Override
public synchronized Entry get(String key) {
CacheHeader entry = mEntries.get(key);
@@ -119,14 +115,15 @@ public class DiskBasedCache implements Cache {
}
File file = getFileForKey(key);
try {
- CountingInputStream cis = new CountingInputStream(
- new BufferedInputStream(createInputStream(file)), file.length());
+ 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);
+ 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;
@@ -146,8 +143,8 @@ public class DiskBasedCache implements Cache {
}
/**
- * Initializes the DiskBasedCache by scanning for all files currently in the
- * specified root directory. Creates the root directory if necessary.
+ * Initializes the DiskBasedCache by scanning for all files currently in the specified root
+ * directory. Creates the root directory if necessary.
*/
@Override
public synchronized void initialize() {
@@ -164,8 +161,9 @@ public class DiskBasedCache implements Cache {
for (File file : files) {
try {
long entrySize = file.length();
- CountingInputStream cis = new CountingInputStream(
- new BufferedInputStream(createInputStream(file)), entrySize);
+ CountingInputStream cis =
+ new CountingInputStream(
+ new BufferedInputStream(createInputStream(file)), entrySize);
try {
CacheHeader entry = CacheHeader.readHeader(cis);
// NOTE: When this entry was put, its size was recorded as data.length, but
@@ -186,6 +184,7 @@ public class DiskBasedCache implements Cache {
/**
* Invalidates an entry in the cache.
+ *
* @param key Cache key
* @param fullExpire True to fully expire the entry, false to soft expire
*/
@@ -201,9 +200,7 @@ public class DiskBasedCache implements Cache {
}
}
- /**
- * Puts the entry with the specified key into the cache.
- */
+ /** Puts the entry with the specified key into the cache. */
@Override
public synchronized void put(String key, Entry entry) {
pruneIfNeeded(entry.data.length);
@@ -229,21 +226,21 @@ public class DiskBasedCache implements Cache {
}
}
- /**
- * Removes the specified key from the cache if it exists.
- */
+ /** Removes the specified key from the cache if it exists. */
@Override
public synchronized void remove(String key) {
boolean deleted = getFileForKey(key).delete();
removeEntry(key);
if (!deleted) {
- VolleyLog.d("Could not delete cache entry for key=%s, filename=%s",
+ VolleyLog.d(
+ "Could not delete cache entry for key=%s, filename=%s",
key, getFilenameForKey(key));
}
}
/**
* Creates a pseudo-unique filename for the specified cache key.
+ *
* @param key The key to generate a file name for.
* @return A pseudo-unique filename.
*/
@@ -254,15 +251,14 @@ public class DiskBasedCache implements Cache {
return localFilename;
}
- /**
- * Returns a file object for the given cache key.
- */
+ /** Returns a file object for the given cache key. */
public File getFileForKey(String key) {
return new File(mRootDirectory, getFilenameForKey(key));
}
/**
* Prunes the cache to fit the amount of bytes specified.
+ *
* @param neededSpace The amount of bytes we are trying to fit into the cache.
*/
private void pruneIfNeeded(int neededSpace) {
@@ -285,8 +281,9 @@ public class DiskBasedCache implements Cache {
if (deleted) {
mTotalSize -= e.size;
} else {
- VolleyLog.d("Could not delete cache entry for key=%s, filename=%s",
- e.key, getFilenameForKey(e.key));
+ VolleyLog.d(
+ "Could not delete cache entry for key=%s, filename=%s",
+ e.key, getFilenameForKey(e.key));
}
iterator.remove();
prunedFiles++;
@@ -297,13 +294,15 @@ public class DiskBasedCache implements Cache {
}
if (VolleyLog.DEBUG) {
- VolleyLog.v("pruned %d files, %d bytes, %d ms",
+ VolleyLog.v(
+ "pruned %d files, %d bytes, %d ms",
prunedFiles, (mTotalSize - before), SystemClock.elapsedRealtime() - startTime);
}
}
/**
* Puts the entry with the specified key into the cache.
+ *
* @param key The key to identify the entry by.
* @param entry The entry to cache.
*/
@@ -317,9 +316,7 @@ public class DiskBasedCache implements Cache {
mEntries.put(key, entry);
}
- /**
- * Removes the entry identified by 'key' from the cache.
- */
+ /** Removes the entry identified by 'key' from the cache. */
private void removeEntry(String key) {
CacheHeader removed = mEntries.remove(key);
if (removed != null) {
@@ -329,11 +326,12 @@ public class DiskBasedCache implements Cache {
/**
* 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
+ // 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.
@@ -345,23 +343,20 @@ public class DiskBasedCache implements Cache {
return bytes;
}
- //VisibleForTesting
+ // VisibleForTesting
InputStream createInputStream(File file) throws FileNotFoundException {
return new FileInputStream(file);
}
- //VisibleForTesting
+ // VisibleForTesting
OutputStream createOutputStream(File file) throws FileNotFoundException {
return new FileOutputStream(file);
}
- /**
- * Handles holding onto the cache headers for an entry.
- */
- //VisibleForTesting
+ /** Handles holding onto the cache headers for an entry. */
+ // VisibleForTesting
static class CacheHeader {
- /** The size of the data identified by this CacheHeader. (This is not
- * serialized to disk. */
+ /** The size of the data identified by this CacheHeader. (This is not serialized to disk. */
long size;
/** The key that identifies the cache entry. */
@@ -385,8 +380,14 @@ public class DiskBasedCache implements Cache {
/** Headers from the response resulting in this cache entry. */
final List<Header> allResponseHeaders;
- private CacheHeader(String key, String etag, long serverDate, long lastModified, long ttl,
- long softTtl, List<Header> allResponseHeaders) {
+ private CacheHeader(
+ String key,
+ String etag,
+ long serverDate,
+ long lastModified,
+ long ttl,
+ long softTtl,
+ List<Header> allResponseHeaders) {
this.key = key;
this.etag = ("".equals(etag)) ? null : etag;
this.serverDate = serverDate;
@@ -398,11 +399,18 @@ public class DiskBasedCache implements Cache {
/**
* Instantiates a new CacheHeader object.
+ *
* @param key The key that identifies the cache entry
* @param entry The cache entry.
*/
CacheHeader(String key, Entry entry) {
- this(key, entry.etag, entry.serverDate, entry.lastModified, entry.ttl, entry.softTtl,
+ this(
+ key,
+ entry.etag,
+ entry.serverDate,
+ entry.lastModified,
+ entry.ttl,
+ entry.softTtl,
getAllResponseHeaders(entry));
size = entry.data.length;
}
@@ -419,6 +427,7 @@ public class DiskBasedCache implements Cache {
/**
* Reads the header from a CountingInputStream and returns a CacheHeader object.
+ *
* @param is The InputStream to read from.
* @throws IOException if fails to read header
*/
@@ -439,9 +448,7 @@ public class DiskBasedCache implements Cache {
key, etag, serverDate, lastModified, ttl, softTtl, allResponseHeaders);
}
- /**
- * Creates a cache entry for the specified data.
- */
+ /** Creates a cache entry for the specified data. */
Entry toCacheEntry(byte[] data) {
Entry e = new Entry();
e.data = data;
@@ -455,9 +462,7 @@ public class DiskBasedCache implements Cache {
return e;
}
- /**
- * Writes the contents of this CacheHeader to the specified OutputStream.
- */
+ /** Writes the contents of this CacheHeader to the specified OutputStream. */
boolean writeHeader(OutputStream os) {
try {
writeInt(os, CACHE_MAGIC);
@@ -477,7 +482,7 @@ public class DiskBasedCache implements Cache {
}
}
- //VisibleForTesting
+ @VisibleForTesting
static class CountingInputStream extends FilterInputStream {
private final long length;
private long bytesRead;
@@ -505,7 +510,7 @@ public class DiskBasedCache implements Cache {
return result;
}
- //VisibleForTesting
+ @VisibleForTesting
long bytesRead() {
return bytesRead;
}
@@ -525,8 +530,8 @@ public class DiskBasedCache implements Cache {
*/
/**
- * Simple wrapper around {@link InputStream#read()} that throws EOFException
- * instead of returning -1.
+ * Simple wrapper around {@link InputStream#read()} that throws EOFException instead of
+ * returning -1.
*/
private static int read(InputStream is) throws IOException {
int b = is.read();
@@ -553,14 +558,14 @@ public class DiskBasedCache implements Cache {
}
static void writeLong(OutputStream os, long n) throws IOException {
- os.write((byte)(n >>> 0));
- os.write((byte)(n >>> 8));
- os.write((byte)(n >>> 16));
- os.write((byte)(n >>> 24));
- os.write((byte)(n >>> 32));
- os.write((byte)(n >>> 40));
- os.write((byte)(n >>> 48));
- os.write((byte)(n >>> 56));
+ os.write((byte) (n >>> 0));
+ os.write((byte) (n >>> 8));
+ os.write((byte) (n >>> 16));
+ os.write((byte) (n >>> 24));
+ os.write((byte) (n >>> 32));
+ os.write((byte) (n >>> 40));
+ os.write((byte) (n >>> 48));
+ os.write((byte) (n >>> 56));
}
static long readLong(InputStream is) throws IOException {
@@ -602,9 +607,11 @@ public class DiskBasedCache implements Cache {
static List<Header> readHeaderList(CountingInputStream cis) throws IOException {
int size = readInt(cis);
- List<Header> result = (size == 0)
- ? Collections.<Header>emptyList()
- : new ArrayList<Header>(size);
+ if (size < 0) {
+ throw new IOException("readHeaderList size=" + size);
+ }
+ List<Header> result =
+ (size == 0) ? Collections.<Header>emptyList() : new ArrayList<Header>();
for (int i = 0; i < size; i++) {
String name = readString(cis).intern();
String value = readString(cis).intern();
@@ -612,5 +619,4 @@ public class DiskBasedCache implements Cache {
}
return result;
}
-
}