aboutsummaryrefslogtreecommitdiff
path: root/src/org/linaro/connect/LRUCache.java
blob: 244ac6bab5185e892940a41b593891055e5f322c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package org.linaro.connect;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * A least recently used cache
 */
class LRUCache extends LinkedHashMap<String, File> {
	private final static long serialVersionUID = 1L;

	private final static int MAX_ENTRIES = 30;

	private final File mCacheDir;

	public LRUCache(File cacheDir) {
		super(MAX_ENTRIES+1, 1, true);
		mCacheDir = cacheDir;

		for( File f: mCacheDir.listFiles() ) {
			String url = toUrl(f);
			put(url, f);
		}
	}

	@Override
	protected boolean removeEldestEntry(Map.Entry<String, File> eldest) {
		return size() > MAX_ENTRIES;
	}

	public InputStream getInputStream(String url) throws IOException {
		File f = get(url);
		if( f != null ) {
			try {
				return new FileInputStream(f);
			}
			catch(IOException e) {
				remove(url);
				f.delete();
				throw e;
			}
		}

		File cacheFile = toCacheFile(url);
		return new CachingInputStream(url, cacheFile);
	}

	private File toCacheFile(String url) {
		//we change /'s to -'s. So we don't loose our -'s we escape them
		String name = url.replace("-", "<DASH>");
		name = name.replace('/', '-');
		return new File(mCacheDir, name);
	}

	private String toUrl(File f) {
		String name = f.getName();
		name = name.replace('-', '/');
		name = name.replace("<DASH>", "-");
		return name;
	}

	private class CachingInputStream extends InputStream {

		String mUrl;
		File mCacheFile;
		InputStream mIn;
		OutputStream mOut;

		public CachingInputStream(String url, File cache)
				throws IOException {
			mUrl = url;
			mCacheFile = cache;
			reset();
		}

		@Override
		public int read() throws IOException {
			throw new IOException("Not Implemented");
		}

		@Override
		public int read(byte[] b) throws IOException {
			return read(b, 0, b.length);
		}

		@Override
		public int read(byte[] b, int offset, int length) throws IOException {
			int bIn = mIn.read(b, offset, length);
			if(bIn != -1)
				mOut.write(b, offset, bIn);
			return bIn;
		}

		@Override
		public synchronized void reset() throws IOException {
			if( mIn != null )
				mIn.close();
			if( mOut != null )
				mOut.close();

			URLConnection c = new URL(mUrl).openConnection();
			mIn = c.getInputStream();
			mOut = new FileOutputStream(mCacheFile);
		}

		@Override
		public void close() throws IOException {
			mIn.close();
			mOut.close();

			put(mUrl, mCacheFile);
		}
	}
}