Mercurial > hg > digilib-old
annotate servlet/src/digilib/io/DocuDirCache.java @ 418:2857846b3fd2
orange + opaque for better visibility
author | hertzhaft |
---|---|
date | Thu, 22 Dec 2005 11:19:40 +0100 |
parents | dd1e681924bf |
children | f8ca069517a2 |
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; | |
270 | 30 import java.util.Map; |
86 | 31 |
181 | 32 import org.apache.log4j.Logger; |
33 | |
259 | 34 import digilib.servlet.DigilibConfiguration; |
35 | |
86 | 36 /** |
37 * @author casties | |
38 */ | |
91 | 39 public class DocuDirCache { |
86 | 40 |
181 | 41 /** general logger for this class */ |
270 | 42 Logger logger = Logger.getLogger(this.getClass()); |
282 | 43 |
159 | 44 /** HashMap of directories */ |
270 | 45 Map map = null; |
282 | 46 |
159 | 47 /** names of base directories */ |
270 | 48 String[] baseDirNames = null; |
282 | 49 |
159 | 50 /** array of allowed file classes (image/text) */ |
51 private int[] fileClasses = null; | |
282 | 52 |
159 | 53 /** number of files in the whole cache (approximate) */ |
270 | 54 long numFiles = 0; |
282 | 55 |
159 | 56 /** number of cache hits */ |
270 | 57 long hits = 0; |
282 | 58 |
159 | 59 /** number of cache misses */ |
270 | 60 long misses = 0; |
282 | 61 |
259 | 62 /** use safe (but slow) indexing */ |
63 boolean safeDirIndex = false; | |
282 | 64 |
270 | 65 /** the root directory element */ |
66 public static Directory ROOT = null; | |
86 | 67 |
176 | 68 /** |
69 * Constructor with array of base directory names and file classes. | |
70 * | |
71 * @param bd | |
72 * base directory names | |
159 | 73 */ |
282 | 74 public DocuDirCache(String[] bd, int[] fileClasses, |
75 DigilibConfiguration dlConfig) { | |
159 | 76 baseDirNames = bd; |
77 map = new HashMap(); | |
78 this.fileClasses = fileClasses; | |
259 | 79 safeDirIndex = dlConfig.getAsBoolean("safe-dir-index"); |
159 | 80 } |
282 | 81 |
176 | 82 /** |
83 * Constructor with array of base directory names. | |
84 * | |
85 * @param bd | |
86 * base directory names | |
86 | 87 */ |
88 public DocuDirCache(String[] bd) { | |
89 baseDirNames = bd; | |
91 | 90 map = new HashMap(); |
159 | 91 // default file class is CLASS_IMAGE |
92 fileClasses = new int[1]; | |
93 fileClasses[0] = FileOps.CLASS_IMAGE; | |
91 | 94 } |
95 | |
176 | 96 /** |
97 * The number of directories in the cache. | |
98 * | |
91 | 99 * @return |
100 */ | |
101 public int size() { | |
102 return (map != null) ? map.size() : 0; | |
86 | 103 } |
104 | |
176 | 105 /** |
106 * Add a DocuDirectory to the cache. | |
86 | 107 * |
108 * @param newdir | |
109 */ | |
110 public void put(DocuDirectory newdir) { | |
111 String s = newdir.getDirName(); | |
91 | 112 if (map.containsKey(s)) { |
197 | 113 logger.warn("Duplicate key in DocuDirCache.put -- ignoring!"); |
86 | 114 } else { |
91 | 115 map.put(s, newdir); |
86 | 116 numFiles += newdir.size(); |
117 } | |
118 } | |
119 | |
176 | 120 /** |
121 * Add a directory to the cache and check its parents. | |
151 | 122 * |
123 * @param newDir | |
124 */ | |
282 | 125 public synchronized void putDir(DocuDirectory newDir) { |
151 | 126 put(newDir); |
270 | 127 String parent = FileOps.parent(newDir.getDirName()); |
128 if (parent != "") { | |
151 | 129 // check the parent in the cache |
176 | 130 DocuDirectory pd = (DocuDirectory) map.get(parent); |
151 | 131 if (pd == null) { |
132 // the parent is unknown | |
133 pd = new DocuDirectory(parent, this); | |
134 putDir(pd); | |
135 } | |
136 newDir.setParent(pd); | |
137 } | |
138 } | |
139 | |
176 | 140 /** |
141 * Get a list with all children of a directory. | |
159 | 142 * |
282 | 143 * Returns a List of DocuDirectory's. Returns an empty List if the directory |
144 * has no children. If recurse is false then only direct children are | |
145 * returned. | |
159 | 146 * |
147 * @param dirname | |
176 | 148 * @param recurse |
149 * find all children and their children. | |
159 | 150 * @return |
151 */ | |
152 public List getChildren(String dirname, boolean recurse) { | |
153 List l = new LinkedList(); | |
176 | 154 for (Iterator i = map.keySet().iterator(); i.hasNext();) { |
209 | 155 String n = (String) i.next(); |
156 DocuDirectory dd = (DocuDirectory) map.get(n); | |
159 | 157 if (recurse) { |
158 if (dd.getDirName().startsWith(dirname)) { | |
159 l.add(dd); | |
160 } | |
161 } else { | |
270 | 162 if (FileOps.parent(dd.getDirName()).equals(dirname)) { |
159 | 163 l.add(dd); |
164 } | |
165 } | |
166 } | |
167 return l; | |
168 } | |
169 | |
176 | 170 /** |
282 | 171 * Returns the DocuDirent with the pathname <code>fn</code> and the index |
172 * <code>in</code> and the class <code>fc</code>. | |
91 | 173 * |
187 | 174 * If <code>fn</code> is a file then the corresponding DocuDirent is |
91 | 175 * returned and the index is ignored. |
176 * | |
176 | 177 * @param fn |
178 * digilib pathname | |
179 * @param in | |
180 * file index | |
246 | 181 * @param fc |
282 | 182 * file class |
176 | 183 * @return |
91 | 184 */ |
159 | 185 public DocuDirent getFile(String fn, int in, int fc) { |
86 | 186 DocuDirectory dd; |
187 // file number is 1-based, vector index is 0-based | |
188 int n = in - 1; | |
189 // first, assume fn is a directory and look in the cache | |
91 | 190 dd = (DocuDirectory) map.get(fn); |
191 if (dd == null) { | |
192 // cache miss | |
193 misses++; | |
176 | 194 /* |
287 | 195 * see if fn is a directory |
176 | 196 */ |
152 | 197 File f = new File(baseDirNames[0], fn); |
91 | 198 if (f.isDirectory()) { |
151 | 199 dd = new DocuDirectory(fn, this); |
91 | 200 if (dd.isValid()) { |
201 // add to the cache | |
151 | 202 putDir(dd); |
91 | 203 } |
204 } else { | |
176 | 205 /* |
206 * maybe it's a file | |
207 */ | |
208 // get the parent directory string (like we store it in the | |
209 // cache) | |
246 | 210 String d = FileOps.parent(fn); |
176 | 211 // try it in the cache |
212 dd = (DocuDirectory) map.get(d); | |
213 if (dd == null) { | |
214 // try to read from disk | |
215 dd = new DocuDirectory(d, this); | |
216 if (dd.isValid()) { | |
217 // add to the cache | |
218 putDir(dd); | |
91 | 219 } else { |
176 | 220 // invalid path |
221 return null; | |
91 | 222 } |
99
226624784fe3
Small bug lead to null pointer exception when directory doesn't exist.
robcast
parents:
91
diff
changeset
|
223 } else { |
176 | 224 // it was not a real cache miss |
225 misses--; | |
91 | 226 } |
176 | 227 // get the file's index |
228 n = dd.indexOf(f.getName(), fc); | |
91 | 229 } |
230 } else { | |
231 // cache hit | |
232 hits++; | |
233 } | |
234 dd.refresh(); | |
235 if (dd.isValid()) { | |
236 try { | |
159 | 237 return dd.get(n, fc); |
187 | 238 } catch (IndexOutOfBoundsException e) { |
91 | 239 } |
240 } | |
241 return null; | |
242 } | |
243 | |
176 | 244 /** |
245 * Returns the DocuDirectory indicated by the pathname <code>fn</code>. | |
91 | 246 * |
247 * If <code>fn</code> is a file then its parent directory is returned. | |
248 * | |
176 | 249 * @param fn |
250 * digilib pathname | |
91 | 251 * @return |
252 */ | |
253 public DocuDirectory getDirectory(String fn) { | |
254 DocuDirectory dd; | |
255 // first, assume fn is a directory and look in the cache | |
256 dd = (DocuDirectory) map.get(fn); | |
86 | 257 if (dd == null) { |
258 // cache miss | |
259 misses++; | |
260 // see if it's a directory | |
152 | 261 File f = new File(baseDirNames[0], fn); |
86 | 262 if (f.isDirectory()) { |
151 | 263 dd = new DocuDirectory(fn, this); |
86 | 264 if (dd.isValid()) { |
265 // add to the cache | |
151 | 266 putDir(dd); |
86 | 267 } |
268 } else { | |
269 // maybe it's a file | |
270 if (f.canRead()) { | |
271 // try the parent directory in the cache | |
91 | 272 dd = (DocuDirectory) map.get(f.getParent()); |
86 | 273 if (dd == null) { |
274 // try to read from disk | |
151 | 275 dd = new DocuDirectory(f.getParent(), this); |
86 | 276 if (dd.isValid()) { |
277 // add to the cache | |
151 | 278 putDir(dd); |
86 | 279 } else { |
280 // invalid path | |
281 return null; | |
282 } | |
91 | 283 } else { |
284 // not a real cache miss then | |
285 misses--; | |
86 | 286 } |
99
226624784fe3
Small bug lead to null pointer exception when directory doesn't exist.
robcast
parents:
91
diff
changeset
|
287 } else { |
226624784fe3
Small bug lead to null pointer exception when directory doesn't exist.
robcast
parents:
91
diff
changeset
|
288 // it's not even a file :-( |
226624784fe3
Small bug lead to null pointer exception when directory doesn't exist.
robcast
parents:
91
diff
changeset
|
289 return null; |
86 | 290 } |
291 } | |
292 } else { | |
293 // cache hit | |
294 hits++; | |
295 } | |
296 dd.refresh(); | |
297 if (dd.isValid()) { | |
298 return dd; | |
299 } | |
300 return null; | |
301 } | |
302 | |
303 /** | |
304 * @return String[] | |
305 */ | |
306 public String[] getBaseDirNames() { | |
307 return baseDirNames; | |
308 } | |
309 | |
310 /** | |
311 * @return long | |
312 */ | |
313 public long getNumFiles() { | |
314 return numFiles; | |
315 } | |
316 | |
317 /** | |
318 * Sets the baseDirNames. | |
176 | 319 * |
320 * @param baseDirNames | |
321 * The baseDirNames to set | |
86 | 322 */ |
323 public void setBaseDirNames(String[] baseDirNames) { | |
324 this.baseDirNames = baseDirNames; | |
325 } | |
326 | |
327 /** | |
328 * @return long | |
329 */ | |
330 public long getHits() { | |
331 return hits; | |
332 } | |
333 | |
334 /** | |
335 * @return long | |
336 */ | |
337 public long getMisses() { | |
338 return misses; | |
339 } | |
340 | |
159 | 341 /** |
342 * @return | |
343 */ | |
344 public int[] getFileClasses() { | |
345 return fileClasses; | |
346 } | |
347 | |
348 /** | |
349 * @param fileClasses | |
350 */ | |
351 public void setFileClasses(int[] fileClasses) { | |
352 this.fileClasses = fileClasses; | |
353 } | |
176 | 354 |
86 | 355 } |