/*******************************************************************************
* Copyright 2011 The Regents of the University of California
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.ohmage;
import android.content.Context;
import com.google.android.filecache.FileResponseCache;
import org.ohmage.logprobe.Log;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.ResponseCache;
import java.net.URI;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
/**
* The {@link OhmageCache} handles storing campaign icons and response images on the sdcard.
*
* <p> Response images are stored on the external sdcard at {@link Context#getExternalCacheDir()}.
* Other icons are stored on the internal cache directory given by {@link Context#getCacheDir()} </p>
*
* @author cketcham
*
*/
public class OhmageCache extends FileResponseCache {
private static final String TAG = "OhmageCache";
private final Context mContext;
public OhmageCache(Context context) {
mContext = context;
}
public static void install(Context context) {
ResponseCache responseCache = ResponseCache.getDefault();
if (responseCache instanceof OhmageCache) {
Log.v(TAG, "Cache has already been installed.");
} else if (responseCache == null) {
OhmageCache dropCache = new OhmageCache(context);
ResponseCache.setDefault(dropCache);
} else {
Class<? extends ResponseCache> type = responseCache.getClass();
Log.e(TAG, "Another ResponseCache has already been installed: " + type);
}
}
public static boolean isResponseImageRequest(URI uri) {
if(uri == null || uri.getHost() == null || uri.getPath() == null)
return false;
URI responseUri = URI.create(ConfigHelper.serverUrl() + OhmageApi.IMAGE_READ_PATH);
return uri.getHost().equals(responseUri.getHost()) && uri.getPath().startsWith(responseUri.getPath());
}
public static File getCachedFile(Context context, URI uri) {
try {
File parent = (isResponseImageRequest(uri)) ? context.getExternalCacheDir() : context.getCacheDir();
if(parent == null)
return null;
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(String.valueOf(uri).getBytes("UTF-8"));
byte[] output = digest.digest();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < output.length; i++) {
builder.append(Integer.toHexString(0xFF & output[i]));
}
return new File(parent, builder.toString());
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "MD5 algorithm not found");
throw new RuntimeException(e);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unsupported Encoding Exception");
throw new RuntimeException(e);
}
}
@Override
protected File getFile(URI uri, String requestMethod, Map<String, List<String>> requestHeaders, Object cookie) {
return getCachedFile(mContext, uri);
}
/**
* Check the current cache useage and delete files if needed
* @param context
* @param maxDiskCacheSize
*/
public static void checkCacheUsage(Context context, int maxDiskCacheSize) {
long size = 0;
File cacheDir = context.getExternalCacheDir();
if(cacheDir == null) {
//sdcard is not available for some reason
return;
}
final File[] fileList = cacheDir.listFiles();
Arrays.sort(fileList, new Comparator<File>() {
@Override
public int compare(File f1, File f2) {
return Long.valueOf(f2.lastModified()).compareTo(
f1.lastModified());
}
});
for (File file : fileList) {
size += file.length();
if (size > maxDiskCacheSize) {
file.delete();
}
}
}
}