Skip to content

Commit

Permalink
move key generator to its own class and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
sjudd committed Nov 5, 2013
1 parent 9600642 commit f59163d
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 81 deletions.
81 changes: 0 additions & 81 deletions library/src/com/bumptech/glide/resize/ImageManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -637,85 +637,4 @@ private void putInMemoryCache(String key, final Bitmap bitmap) {
memoryCache.put(key, bitmap);
}
}

private static class SafeKeyGenerator {
private final Map<LoadId, String> loadIdToSafeHash = new HashMap<LoadId, String>();
private final ByteBuffer byteBuffer = ByteBuffer.allocate(8);
private MessageDigest messageDigest;

public SafeKeyGenerator() {
try {
messageDigest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}

public String getSafeKey(String id, Transformation transformation, Downsampler downsampler, int width, int height) {
LoadId loadId = new LoadId(id, transformation.getId(), downsampler.getId(), width, height);
String safeKey = loadIdToSafeHash.get(loadId);
if (safeKey == null) {
try {
safeKey = loadId.generateSafeKey();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
loadIdToSafeHash.put(loadId, safeKey);
}
return safeKey;
}

private class LoadId {
private final String id;
private final String transformationId;
private final String downsamplerId;
private final int width;
private final int height;

public LoadId(String id, String transformationId, String downsamplerId, int width, int height) {
this.id = id;
this.transformationId = transformationId;
this.downsamplerId = downsamplerId;
this.width = width;
this.height = height;
}

public String generateSafeKey() throws UnsupportedEncodingException {
messageDigest.update(id.getBytes("UTF-8"));
messageDigest.update(transformationId.getBytes("UTF-8"));
messageDigest.update(downsamplerId.getBytes("UTF-8"));
byteBuffer.position(0);
byteBuffer.putInt(width);
byteBuffer.putInt(height);
messageDigest.update(byteBuffer.array());
return Util.sha256BytesToHex(messageDigest.digest());
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

LoadId loadId = (LoadId) o;

if (height != loadId.height) return false;
if (width != loadId.width) return false;
if (!downsamplerId.equals(loadId.downsamplerId)) return false;
if (!id.equals(loadId.id)) return false;
if (!transformationId.equals(loadId.transformationId)) return false;

return true;
}

@Override
public int hashCode() {
int result = id.hashCode();
result = 31 * result + transformationId.hashCode();
result = 31 * result + downsamplerId.hashCode();
result = 31 * result + width;
result = 31 * result + height;
return result;
}
}
}
}
128 changes: 128 additions & 0 deletions library/src/com/bumptech/glide/resize/SafeKeyGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package com.bumptech.glide.resize;

import android.os.Build;
import com.bumptech.glide.resize.load.Downsampler;
import com.bumptech.glide.resize.load.Transformation;
import com.bumptech.glide.util.Util;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

public class SafeKeyGenerator {
private final Map<LoadId, String> loadIdToSafeHash = new HashMap<LoadId, String>();
private final ByteBuffer byteBuffer = ByteBuffer.allocate(8);
private final LoadIdPool loadIdPool = new LoadIdPool();
private MessageDigest messageDigest;

public SafeKeyGenerator() {
try {
messageDigest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}

public String getSafeKey(String id, Transformation transformation, Downsampler downsampler, int width, int height) {
LoadId loadId = loadIdPool.get(id, transformation.getId(), downsampler.getId(), width, height);
String safeKey = loadIdToSafeHash.get(loadId);
if (safeKey == null) {
try {
safeKey = loadId.generateSafeKey();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
loadIdToSafeHash.put(loadId, safeKey);
} else {
loadIdPool.offer(loadId);
}
return safeKey;
}

private class LoadIdPool {
private static final int MAX_SIZE = 20;
private Queue<LoadId> loadIdQueue;

public LoadIdPool() {
if (Build.VERSION.SDK_INT >= 9) {
loadIdQueue = new ArrayDeque<LoadId>(MAX_SIZE);
} else {
loadIdQueue = new LinkedList<LoadId>();
}
}

public LoadId get(String id, String transformationId, String downsamplerId, int width, int height) {
LoadId loadId = loadIdQueue.poll();
if (loadId == null) {
loadId = new LoadId();
}
loadId.init(id, transformationId, downsamplerId, width, height);
return loadId;
}

public void offer(LoadId loadId) {
if (loadIdQueue.size() < MAX_SIZE) {
loadIdQueue.offer(loadId);
}
}
}

private class LoadId {
private String id;
private String transformationId;
private String downsamplerId;
private int width;
private int height;

public void init(String id, String transformationId, String downsamplerId, int width, int height) {
this.id = id;
this.transformationId = transformationId;
this.downsamplerId = downsamplerId;
this.width = width;
this.height = height;
}

public String generateSafeKey() throws UnsupportedEncodingException {
messageDigest.update(id.getBytes("UTF-8"));
messageDigest.update(transformationId.getBytes("UTF-8"));
messageDigest.update(downsamplerId.getBytes("UTF-8"));
byteBuffer.position(0);
byteBuffer.putInt(width);
byteBuffer.putInt(height);
messageDigest.update(byteBuffer.array());
return Util.sha256BytesToHex(messageDigest.digest());
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

LoadId loadId = (LoadId) o;

if (height != loadId.height) return false;
if (width != loadId.width) return false;
if (!downsamplerId.equals(loadId.downsamplerId)) return false;
if (!id.equals(loadId.id)) return false;
if (!transformationId.equals(loadId.transformationId)) return false;

return true;
}

@Override
public int hashCode() {
int result = id.hashCode();
result = 31 * result + transformationId.hashCode();
result = 31 * result + downsamplerId.hashCode();
result = 31 * result + width;
result = 31 * result + height;
return result;
}
}
}
71 changes: 71 additions & 0 deletions library/tests/src/com/bumptech/glide/KeyGeneratorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.bumptech.glide;

import android.graphics.Bitmap;
import android.test.AndroidTestCase;
import com.bumptech.glide.resize.SafeKeyGenerator;
import com.bumptech.glide.resize.bitmap_recycle.BitmapPool;
import com.bumptech.glide.resize.load.Downsampler;
import com.bumptech.glide.resize.load.Transformation;

import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class KeyGeneratorTest extends AndroidTestCase {
private SafeKeyGenerator keyGenerator;

@Override
protected void setUp() throws Exception {
super.setUp();
keyGenerator = new SafeKeyGenerator();
}

public void testKeysAreValidForDiskCache() {
String key;
final Pattern diskCacheRegex = Pattern.compile("[a-z0-9_-]{64}");
for (int i = 0; i < 1000; i++) {
key = getRandomKeyFromGenerator();
final Matcher matcher = diskCacheRegex.matcher(key);
assertTrue(matcher.matches());
}
}

private String getRandomKeyFromGenerator() {
return keyGenerator.getSafeKey(getRandomId(), new RandomTransformation(), new RandomDownsampler(),
getRandomDimen(), getRandomDimen());
}

private static int getRandomDimen() {
return (int) Math.round(Math.random() * 1000);
}

private static String getRandomId() {
return UUID.randomUUID().toString();
}

private static class RandomDownsampler extends Downsampler {

@Override
protected int getSampleSize(int inWidth, int inHeight, int outWidth, int outHeight) {
return 0;
}

@Override
public String getId() {
return getRandomId();
}
}

private static class RandomTransformation extends Transformation {

@Override
public Bitmap transform(Bitmap bitmap, BitmapPool pool, int outWidth, int outHeight) {
return null;
}

@Override
public String getId() {
return getRandomId();
}
}
}

0 comments on commit f59163d

Please sign in to comment.