package com.github.droidfu.cachefu; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import android.os.Parcel; /** * Allows caching Model objects using the features provided by {@link AbstractCache}. The key into * the cache will be based around the cached object's key, and the object will be able to save and * reload itself from the cache. * * @author Michael England * */ public class ModelCache extends AbstractCache<String, CachedModel> { /** * Creates an {@link AbstractCache} with params provided and name 'ModelCache'. * * @see com.github.droidfu.cachefu.AbstractCache#AbstractCache(java.lang.String, int, long, int) */ public ModelCache(int initialCapacity, long expirationInMinutes, int maxConcurrentThreads) { super("ModelCache", initialCapacity, expirationInMinutes, maxConcurrentThreads); } // Counter for all saves to cache. Used to determine if newer object in cache private long transactionCount = Long.MIN_VALUE + 1; /** * @see com.github.droidfu.cachefu.AbstractCache#put(java.lang.Object, java.lang.Object) */ @Override public synchronized CachedModel put(String key, CachedModel value) { // Set transaction id for checking validity against other values with same key value.setTransactionId(transactionCount++); return super.put(key, value); } /** * Removes all cached objects with key prefix. * * @param prefix * Prefix of all cached object keys to be removed */ public synchronized void removeAllWithPrefix(String prefix) { CacheHelper.removeAllWithStringPrefix(this, prefix); } /** * @see com.github.droidfu.cachefu.AbstractCache#getFileNameForKey(java.lang.Object) */ @Override public String getFileNameForKey(String url) { return CacheHelper.getFileNameFromUrl(url); } /** * @see com.github.droidfu.cachefu.AbstractCache#readValueFromDisk(java.io.File) */ @Override protected CachedModel readValueFromDisk(File file) throws IOException { FileInputStream istream = new FileInputStream(file); // Read file into byte array byte[] dataWritten = new byte[(int) file.length()]; BufferedInputStream bistream = new BufferedInputStream(istream); bistream.read(dataWritten); bistream.close(); // Create parcel with cached data Parcel parcelIn = Parcel.obtain(); parcelIn.unmarshall(dataWritten, 0, dataWritten.length); parcelIn.setDataPosition(0); // Read class name from parcel and use the class loader to read parcel String className = parcelIn.readString(); // In case this sometimes hits a null value if (className == null) { return null; } Class<?> clazz; try { clazz = Class.forName(className); return parcelIn.readParcelable(clazz.getClassLoader()); } catch (ClassNotFoundException e) { throw new IOException(e.getMessage()); } } /** * @see com.github.droidfu.cachefu.AbstractCache#writeValueToDisk(java.io.File, * java.lang.Object) */ @Override protected void writeValueToDisk(File file, CachedModel data) throws IOException { // Write object into parcel Parcel parcelOut = Parcel.obtain(); parcelOut.writeString(data.getClass().getCanonicalName()); parcelOut.writeParcelable(data, 0); // Write byte data to file FileOutputStream ostream = new FileOutputStream(file); BufferedOutputStream bistream = new BufferedOutputStream(ostream); bistream.write(parcelOut.marshall()); bistream.close(); } }