1 package org.lcsim.util.cache;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.OutputStream;
8 import java.io.PrintStream;
9 import java.net.URL;
10 import java.net.URLConnection;
11 import java.net.URLEncoder;
12
13
14
15
16
17 public class FileCache {
18 private static final File home = new File(getCacheRoot(), ".cache");
19 private static final ByteFormat format = new ByteFormat();
20 private File cache;
21 private PrintStream print = System.out;
22
23 public static File getCacheRoot() {
24 String cacheDir = System.getProperty("org.lcsim.cacheDir");
25 if (cacheDir == null)
26 cacheDir = System.getProperty("user.home");
27 return new File(cacheDir);
28 }
29
30
31
32
33
34 public FileCache() throws IOException {
35 this(home);
36 }
37
38
39
40
41
42
43 public FileCache(File cacheDirectory) throws IOException {
44 setCacheDirectory(cacheDirectory);
45 }
46
47
48
49
50
51
52
53
54
55
56 public File getCachedFile(URL url) throws IOException {
57 return getCachedFile(url, null);
58 }
59
60
61
62
63
64
65
66
67
68
69
70
71
72 public File getCachedFile(URL url, Validator validator) throws IOException {
73 File cacheFile = new File(cache, URLEncoder.encode(url.toExternalForm(), "UTF-8"));
74 boolean downloadRequired = !cacheFile.exists();
75 if (cacheFile.exists() && !Boolean.getBoolean("org.lcsim.offline")) {
76
77 try {
78 URLConnection connection = url.openConnection();
79 connection.setConnectTimeout(5000);
80 connection.setReadTimeout(5000);
81 long updated = connection.getLastModified();
82 long cached = cacheFile.lastModified();
83 if (updated > cached)
84 downloadRequired = true;
85 } catch (IOException x) {
86
87
88 }
89 }
90 if (downloadRequired) {
91 URLConnection connection = url.openConnection();
92 connection.setConnectTimeout(10000);
93 connection.setReadTimeout(10000);
94 long size = connection.getContentLength();
95 InputStream in = connection.getInputStream();
96 if (in != null) {
97 if (print != null)
98 print.println("Downloading..." + url);
99 File temp = File.createTempFile("det", null, cache);
100 temp.deleteOnExit();
101 OutputStream out = new FileOutputStream(temp);
102 byte[] buffer = new byte[8096];
103 try {
104 long got = 0;
105 for (;;) {
106 int l = in.read(buffer);
107 if (l < 0)
108 break;
109 out.write(buffer, 0, l);
110 if (out != null) {
111 got += l;
112 if (print != null) {
113 print.print("Got ");
114 print.print(format.format(got));
115 print.print('/');
116 print.print(format.format(size));
117 print.print('\r');
118 print.flush();
119 }
120 }
121 }
122 } finally {
123 in.close();
124 out.close();
125 }
126 if (validator != null)
127 validator.checkValidity(url, temp);
128
129 if (cacheFile.exists()) {
130 boolean ok = cacheFile.delete();
131 if (!ok)
132 throw new IOException("Error while deleting old cache file");
133 }
134 boolean ok = temp.renameTo(cacheFile);
135 if (!ok)
136 throw new IOException("Error while moving file to cache");
137 } else
138 throw new IOException("Could not open " + url);
139 }
140 return cacheFile;
141 }
142
143
144
145
146
147 public File getCacheDirectory() {
148 return this.cache;
149 }
150
151
152
153
154
155
156
157 public void setCacheDirectory(File cacheDirectory) throws IOException {
158 if (!cacheDirectory.exists()) {
159 boolean ok = cacheDirectory.mkdirs();
160 if (!ok)
161 throw new IOException("Unable to create: " + cacheDirectory.getAbsoluteFile());
162 } else if (!cacheDirectory.isDirectory()) {
163 throw new IOException("Not a directory");
164 }
165 this.cache = cacheDirectory;
166 }
167
168
169
170
171
172
173
174 public PrintStream getPrintStream() {
175
176 return this.print;
177 }
178
179
180
181
182
183
184 public void setPrintStream(PrintStream printStream) {
185 this.print = printStream;
186 }
187
188
189
190
191
192 public static interface Validator {
193
194
195
196
197
198
199
200
201 void checkValidity(URL url, File file) throws IOException;
202 }
203 }