Mercurial > hg > digilib-old
annotate servlet/src/digilib/io/DocuDirCache.java @ 259:beed92ee6022
Servlet version 1.21b1
- directory indexing got faster but less safe
(configurable by "safe-dir-index")
- mo=rawfile supplies filename
- DigilibConfig takes File parameters
- some SerialVersionUIDs (suggested by Eclipse)
author | robcast |
---|---|
date | Mon, 11 Oct 2004 21:23:00 +0200 |
parents | aaf6eace011d |
children | b21915a3fc24 |
rev | line source |
---|---|
176 | 1 /* |
2 * DocuDirCache.java | |
3 * | |
4 * Digital Image Library servlet components | |
5 * | |
6 * Copyright (C) 2003 Robert Casties (robcast@mail.berlios.de) | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify it | |
9 * under the terms of the GNU General Public License as published by the Free | |
10 * Software Foundation; either version 2 of the License, or (at your option) | |
11 * any later version. | |
12 * | |
13 * Please read license.txt for the full details. A copy of the GPL may be found | |
14 * at http://www.gnu.org/copyleft/lgpl.html | |
15 * | |
16 * You should have received a copy of the GNU General Public License along with | |
17 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | |
18 * Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
86 | 20 * Created on 03.03.2003 |
21 */ | |
22 | |
23 package digilib.io; | |
24 | |
25 import java.io.File; | |
91 | 26 import java.util.HashMap; |
159 | 27 import java.util.Iterator; |
28 import java.util.LinkedList; | |
29 import java.util.List; | |
86 | 30 |
181 | 31 import org.apache.log4j.Logger; |
32 | |
259 | 33 import digilib.servlet.DigilibConfiguration; |
34 | |
86 | 35 /** |
36 * @author casties | |
37 */ | |
91 | 38 public class DocuDirCache { |
86 | 39 |
181 | 40 /** general logger for this class */ |
41 protected Logger logger = Logger.getLogger(this.getClass()); | |
159 | 42 /** HashMap of directories */ |
176 | 43 protected HashMap map = null; |
159 | 44 /** names of base directories */ |
86 | 45 private String[] baseDirNames = null; |
159 | 46 /** array of allowed file classes (image/text) */ |
47 private int[] fileClasses = null; | |
48 /** number of files in the whole cache (approximate) */ | |
86 | 49 private long numFiles = 0; |
159 | 50 /** number of cache hits */ |
86 | 51 private long hits = 0; |
159 | 52 /** number of cache misses */ |
86 | 53 private long misses = 0; |
259 | 54 /** use safe (but slow) indexing */ |
55 boolean safeDirIndex = false; | |
86 | 56 |
176 | 57 /** |
58 * Constructor with array of base directory names and file classes. | |
59 * | |
60 * @param bd | |
61 * base directory names | |
159 | 62 */ |
259 | 63 public DocuDirCache(String[] bd, int[] fileClasses, DigilibConfiguration dlConfig) { |
159 | 64 baseDirNames = bd; |
65 map = new HashMap(); | |
66 this.fileClasses = fileClasses; | |
259 | 67 safeDirIndex = dlConfig.getAsBoolean("safe-dir-index"); |
159 | 68 } |
176 | 69 /** |
70 * Constructor with array of base directory names. | |
71 * | |
72 * @param bd | |
73 * base directory names | |
86 | 74 */ |
75 public DocuDirCache(String[] bd) { | |
76 baseDirNames = bd; | |
91 | 77 map = new HashMap(); |
159 | 78 // default file class is CLASS_IMAGE |
79 fileClasses = new int[1]; | |
80 fileClasses[0] = FileOps.CLASS_IMAGE; | |
91 | 81 } |
82 | |
176 | 83 /** |
84 * The number of directories in the cache. | |
85 * | |
91 | 86 * @return |
87 */ | |
88 public int size() { | |
89 return (map != null) ? map.size() : 0; | |
86 | 90 } |
91 | |
176 | 92 /** |
93 * Add a DocuDirectory to the cache. | |
86 | 94 * |
95 * @param newdir | |
96 */ | |
97 public void put(DocuDirectory newdir) { | |
98 String s = newdir.getDirName(); | |
91 | 99 if (map.containsKey(s)) { |
197 | 100 logger.warn("Duplicate key in DocuDirCache.put -- ignoring!"); |
86 | 101 } else { |
91 | 102 map.put(s, newdir); |
86 | 103 numFiles += newdir.size(); |
104 } | |
105 } | |
106 | |
176 | 107 /** |
108 * Add a directory to the cache and check its parents. | |
151 | 109 * |
110 * @param newDir | |
111 */ | |
112 public void putDir(DocuDirectory newDir) { | |
113 put(newDir); | |
114 String parent = newDir.getParentDirName(); | |
115 if (parent != null) { | |
116 // check the parent in the cache | |
176 | 117 DocuDirectory pd = (DocuDirectory) map.get(parent); |
151 | 118 if (pd == null) { |
119 // the parent is unknown | |
120 pd = new DocuDirectory(parent, this); | |
121 putDir(pd); | |
122 } | |
123 newDir.setParent(pd); | |
124 } | |
125 } | |
126 | |
176 | 127 /** |
128 * Get a list with all children of a directory. | |
159 | 129 * |
176 | 130 * Returns a List of DocuDirectory's. Returns an empty List if the |
131 * directory has no children. If recurse is false then only direct children | |
132 * are returned. | |
159 | 133 * |
134 * @param dirname | |
176 | 135 * @param recurse |
136 * find all children and their children. | |
159 | 137 * @return |
138 */ | |
139 public List getChildren(String dirname, boolean recurse) { | |
140 List l = new LinkedList(); | |
176 | 141 for (Iterator i = map.keySet().iterator(); i.hasNext();) { |
209 | 142 String n = (String) i.next(); |
143 DocuDirectory dd = (DocuDirectory) map.get(n); | |
159 | 144 if (recurse) { |
145 if (dd.getDirName().startsWith(dirname)) { | |
146 l.add(dd); | |
147 } | |
148 } else { | |
149 if (dd.getParentDirName().equals(dirname)) { | |
150 l.add(dd); | |
151 } | |
152 } | |
153 } | |
154 return l; | |
155 } | |
156 | |
176 | 157 /** |
187 | 158 * Returns the DocuDirent with the pathname <code>fn</code> and the |
159 | 159 * index <code>in</code> and the class <code>fc</code>. |
91 | 160 * |
187 | 161 * If <code>fn</code> is a file then the corresponding DocuDirent is |
91 | 162 * returned and the index is ignored. |
163 * | |
176 | 164 * @param fn |
165 * digilib pathname | |
166 * @param in | |
167 * file index | |
246 | 168 * @param fc |
169 * file class | |
176 | 170 * @return |
91 | 171 */ |
159 | 172 public DocuDirent getFile(String fn, int in, int fc) { |
86 | 173 DocuDirectory dd; |
174 // file number is 1-based, vector index is 0-based | |
175 int n = in - 1; | |
176 // first, assume fn is a directory and look in the cache | |
91 | 177 dd = (DocuDirectory) map.get(fn); |
178 if (dd == null) { | |
179 // cache miss | |
180 misses++; | |
176 | 181 /* |
182 * see if it's a directory | |
183 */ | |
152 | 184 File f = new File(baseDirNames[0], fn); |
91 | 185 if (f.isDirectory()) { |
151 | 186 dd = new DocuDirectory(fn, this); |
91 | 187 if (dd.isValid()) { |
188 // add to the cache | |
151 | 189 putDir(dd); |
91 | 190 } |
191 } else { | |
176 | 192 /* |
193 * maybe it's a file | |
194 */ | |
195 // get the parent directory string (like we store it in the | |
196 // cache) | |
246 | 197 String d = FileOps.parent(fn); |
176 | 198 // try it in the cache |
199 dd = (DocuDirectory) map.get(d); | |
200 if (dd == null) { | |
201 // try to read from disk | |
202 dd = new DocuDirectory(d, this); | |
203 if (dd.isValid()) { | |
204 // add to the cache | |
205 putDir(dd); | |
91 | 206 } else { |
176 | 207 // invalid path |
208 return null; | |
91 | 209 } |
99
226624784fe3
Small bug lead to null pointer exception when directory doesn't exist.
robcast
parents:
91
diff
changeset
|
210 } else { |
176 | 211 // it was not a real cache miss |
212 misses--; | |
91 | 213 } |
176 | 214 // get the file's index |
215 n = dd.indexOf(f.getName(), fc); | |
91 | 216 } |
217 } else { | |
218 // cache hit | |
219 hits++; | |
220 } | |
221 dd.refresh(); | |
222 if (dd.isValid()) { | |
223 try { | |
159 | 224 return dd.get(n, fc); |
187 | 225 } catch (IndexOutOfBoundsException e) { |
91 | 226 } |
227 } | |
228 return null; | |
229 } | |
230 | |
176 | 231 /** |
232 * Returns the DocuDirectory indicated by the pathname <code>fn</code>. | |
91 | 233 * |
234 * If <code>fn</code> is a file then its parent directory is returned. | |
235 * | |
176 | 236 * @param fn |
237 * digilib pathname | |
91 | 238 * @return |
239 */ | |
240 public DocuDirectory getDirectory(String fn) { | |
241 DocuDirectory dd; | |
242 // first, assume fn is a directory and look in the cache | |
243 dd = (DocuDirectory) map.get(fn); | |
86 | 244 if (dd == null) { |
245 // cache miss | |
246 misses++; | |
247 // see if it's a directory | |
152 | 248 File f = new File(baseDirNames[0], fn); |
86 | 249 if (f.isDirectory()) { |
151 | 250 dd = new DocuDirectory(fn, this); |
86 | 251 if (dd.isValid()) { |
252 // add to the cache | |
151 | 253 putDir(dd); |
86 | 254 } |
255 } else { | |
256 // maybe it's a file | |
257 if (f.canRead()) { | |
258 // try the parent directory in the cache | |
91 | 259 dd = (DocuDirectory) map.get(f.getParent()); |
86 | 260 if (dd == null) { |
261 // try to read from disk | |
151 | 262 dd = new DocuDirectory(f.getParent(), this); |
86 | 263 if (dd.isValid()) { |
264 // add to the cache | |
151 | 265 putDir(dd); |
86 | 266 } else { |
267 // invalid path | |
268 return null; | |
269 } | |
91 | 270 } else { |
271 // not a real cache miss then | |
272 misses--; | |
86 | 273 } |
99
226624784fe3
Small bug lead to null pointer exception when directory doesn't exist.
robcast
parents:
91
diff
changeset
|
274 } else { |
226624784fe3
Small bug lead to null pointer exception when directory doesn't exist.
robcast
parents:
91
diff
changeset
|
275 // it's not even a file :-( |
226624784fe3
Small bug lead to null pointer exception when directory doesn't exist.
robcast
parents:
91
diff
changeset
|
276 return null; |
86 | 277 } |
278 } | |
279 } else { | |
280 // cache hit | |
281 hits++; | |
282 } | |
283 dd.refresh(); | |
284 if (dd.isValid()) { | |
285 return dd; | |
286 } | |
287 return null; | |
288 } | |
289 | |
290 /** | |
291 * @return String[] | |
292 */ | |
293 public String[] getBaseDirNames() { | |
294 return baseDirNames; | |
295 } | |
296 | |
297 /** | |
298 * @return long | |
299 */ | |
300 public long getNumFiles() { | |
301 return numFiles; | |
302 } | |
303 | |
304 /** | |
305 * Sets the baseDirNames. | |
176 | 306 * |
307 * @param baseDirNames | |
308 * The baseDirNames to set | |
86 | 309 */ |
310 public void setBaseDirNames(String[] baseDirNames) { | |
311 this.baseDirNames = baseDirNames; | |
312 } | |
313 | |
314 /** | |
315 * @return long | |
316 */ | |
317 public long getHits() { | |
318 return hits; | |
319 } | |
320 | |
321 /** | |
322 * @return long | |
323 */ | |
324 public long getMisses() { | |
325 return misses; | |
326 } | |
327 | |
159 | 328 /** |
329 * @return | |
330 */ | |
331 public int[] getFileClasses() { | |
332 return fileClasses; | |
333 } | |
334 | |
335 /** | |
336 * @param fileClasses | |
337 */ | |
338 public void setFileClasses(int[] fileClasses) { | |
339 this.fileClasses = fileClasses; | |
340 } | |
176 | 341 |
86 | 342 } |