Mercurial > hg > digilib-old
annotate common/src/main/java/digilib/io/DocuDirCache.java @ 903:7779b37d1d05
refactored into maven modules per servlet type.
can build servlet-api 2.3 and 3.0 via profile now!
author | robcast |
---|---|
date | Tue, 26 Apr 2011 20:24:31 +0200 |
parents | servlet/src/main/java/digilib/io/DocuDirCache.java@ba1eb2d821a2 |
children | 7bcc6765c209 |
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; | |
159 | 26 import java.util.LinkedList; |
27 import java.util.List; | |
758 | 28 import java.util.concurrent.ConcurrentHashMap; |
759 | 29 import java.util.concurrent.ConcurrentMap; |
86 | 30 |
181 | 31 import org.apache.log4j.Logger; |
32 | |
563 | 33 import digilib.io.FileOps.FileClass; |
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 */ |
759 | 45 ConcurrentMap<String, DocuDirectory> map = new ConcurrentHashMap<String, DocuDirectory>(); |
282 | 46 |
159 | 47 /** names of base directories */ |
270 | 48 String[] baseDirNames = null; |
282 | 49 |
159 | 50 /** array of allowed file classes (image/text) */ |
563 | 51 private FileClass[] 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 |
270 | 62 /** the root directory element */ |
63 public static Directory ROOT = null; | |
86 | 64 |
176 | 65 /** |
66 * Constructor with array of base directory names and file classes. | |
67 * | |
68 * @param bd | |
69 * base directory names | |
159 | 70 */ |
563 | 71 public DocuDirCache(String[] bd, FileClass[] fcs, |
282 | 72 DigilibConfiguration dlConfig) { |
159 | 73 baseDirNames = bd; |
563 | 74 this.fileClasses = fcs; |
159 | 75 } |
282 | 76 |
176 | 77 /** |
78 * Constructor with array of base directory names. | |
79 * | |
80 * @param bd | |
81 * base directory names | |
86 | 82 */ |
83 public DocuDirCache(String[] bd) { | |
84 baseDirNames = bd; | |
159 | 85 // default file class is CLASS_IMAGE |
563 | 86 fileClasses = new FileClass[] { FileClass.IMAGE }; |
91 | 87 } |
88 | |
176 | 89 /** |
90 * The number of directories in the cache. | |
91 * | |
91 | 92 * @return |
93 */ | |
94 public int size() { | |
95 return (map != null) ? map.size() : 0; | |
86 | 96 } |
97 | |
176 | 98 /** |
99 * Add a DocuDirectory to the cache. | |
759 | 100 * Always returns the correct Object from the cache, |
101 * either newdir one or another one. | |
86 | 102 * |
103 * @param newdir | |
759 | 104 * @return dir |
86 | 105 */ |
759 | 106 public DocuDirectory put(DocuDirectory newdir) { |
86 | 107 String s = newdir.getDirName(); |
750 | 108 logger.debug("DocuDirCache.put for "+s+" in "+this); |
759 | 109 DocuDirectory olddir = map.putIfAbsent(s, newdir); |
110 if (olddir != null) { | |
197 | 111 logger.warn("Duplicate key in DocuDirCache.put -- ignoring!"); |
759 | 112 return olddir; |
86 | 113 } |
759 | 114 numFiles += newdir.size(); |
115 return newdir; | |
86 | 116 } |
117 | |
176 | 118 /** |
119 * Add a directory to the cache and check its parents. | |
759 | 120 * Always returns the correct Object from the cache, |
121 * either newDir one or another one. | |
122 * | |
151 | 123 * @param newDir |
759 | 124 * @return dir |
151 | 125 */ |
759 | 126 public DocuDirectory putDir(DocuDirectory newDir) { |
127 DocuDirectory dd = put(newDir); | |
128 if (dd.getParent() == null) { | |
129 // no parent link yet | |
130 String parent = FileOps.parent(newDir.getDirName()); | |
131 if (parent != "") { | |
132 // check the parent in the cache | |
133 DocuDirectory pd = map.get(parent); | |
134 if (pd == null) { | |
135 // the parent is unknown | |
136 pd = new DocuDirectory(parent, this); | |
137 pd = putDir(pd); | |
138 } | |
139 newDir.setParent(pd); | |
151 | 140 } |
141 } | |
759 | 142 return dd; |
151 | 143 } |
144 | |
176 | 145 /** |
146 * Get a list with all children of a directory. | |
159 | 147 * |
282 | 148 * Returns a List of DocuDirectory's. Returns an empty List if the directory |
149 * has no children. If recurse is false then only direct children are | |
150 * returned. | |
159 | 151 * |
152 * @param dirname | |
176 | 153 * @param recurse |
154 * find all children and their children. | |
159 | 155 * @return |
156 */ | |
531 | 157 public List<DocuDirectory> getChildren(String dirname, boolean recurse) { |
158 List<DocuDirectory> l = new LinkedList<DocuDirectory>(); | |
159 for (DocuDirectory dd: map.values()) { | |
159 | 160 if (recurse) { |
161 if (dd.getDirName().startsWith(dirname)) { | |
162 l.add(dd); | |
163 } | |
164 } else { | |
270 | 165 if (FileOps.parent(dd.getDirName()).equals(dirname)) { |
159 | 166 l.add(dd); |
167 } | |
168 } | |
169 } | |
170 return l; | |
171 } | |
172 | |
176 | 173 /** |
282 | 174 * Returns the DocuDirent with the pathname <code>fn</code> and the index |
175 * <code>in</code> and the class <code>fc</code>. | |
91 | 176 * |
187 | 177 * If <code>fn</code> is a file then the corresponding DocuDirent is |
91 | 178 * returned and the index is ignored. |
179 * | |
176 | 180 * @param fn |
181 * digilib pathname | |
182 * @param in | |
183 * file index | |
246 | 184 * @param fc |
282 | 185 * file class |
176 | 186 * @return |
91 | 187 */ |
563 | 188 public DocuDirent getFile(String fn, int in, FileClass fc) { |
86 | 189 DocuDirectory dd; |
190 // file number is 1-based, vector index is 0-based | |
191 int n = in - 1; | |
192 // first, assume fn is a directory and look in the cache | |
563 | 193 dd = map.get(fn); |
91 | 194 if (dd == null) { |
195 // cache miss | |
196 misses++; | |
176 | 197 /* |
287 | 198 * see if fn is a directory |
176 | 199 */ |
152 | 200 File f = new File(baseDirNames[0], fn); |
91 | 201 if (f.isDirectory()) { |
472
f8ca069517a2
Bugfix for images not found in dir: added sorting for ArrayLists of ImageFilesets
hertzhaft
parents:
287
diff
changeset
|
202 // logger.debug(fn + " is a dir"); |
151 | 203 dd = new DocuDirectory(fn, this); |
91 | 204 if (dd.isValid()) { |
205 // add to the cache | |
759 | 206 dd = putDir(dd); |
91 | 207 } |
208 } else { | |
176 | 209 /* |
210 * maybe it's a file | |
211 */ | |
212 // get the parent directory string (like we store it in the | |
213 // cache) | |
246 | 214 String d = FileOps.parent(fn); |
176 | 215 // try it in the cache |
472
f8ca069517a2
Bugfix for images not found in dir: added sorting for ArrayLists of ImageFilesets
hertzhaft
parents:
287
diff
changeset
|
216 // logger.debug(fn + " is a file in dir " + d); |
563 | 217 dd = map.get(d); |
176 | 218 if (dd == null) { |
219 // try to read from disk | |
220 dd = new DocuDirectory(d, this); | |
221 if (dd.isValid()) { | |
222 // add to the cache | |
472
f8ca069517a2
Bugfix for images not found in dir: added sorting for ArrayLists of ImageFilesets
hertzhaft
parents:
287
diff
changeset
|
223 // logger.debug(dd + " is valid"); |
759 | 224 dd = putDir(dd); |
91 | 225 } else { |
176 | 226 // invalid path |
227 return null; | |
91 | 228 } |
99
226624784fe3
Small bug lead to null pointer exception when directory doesn't exist.
robcast
parents:
91
diff
changeset
|
229 } else { |
176 | 230 // it was not a real cache miss |
231 misses--; | |
91 | 232 } |
176 | 233 // get the file's index |
234 n = dd.indexOf(f.getName(), fc); | |
91 | 235 } |
236 } else { | |
237 // cache hit | |
238 hits++; | |
239 } | |
240 dd.refresh(); | |
241 if (dd.isValid()) { | |
242 try { | |
159 | 243 return dd.get(n, fc); |
187 | 244 } catch (IndexOutOfBoundsException e) { |
473
fca40a188a22
modified DocuDirent.compareTo instead of ImageFileset.compareTo
hertzhaft
parents:
472
diff
changeset
|
245 // logger.debug(fn + " not found in directory"); |
91 | 246 } |
247 } | |
248 return null; | |
249 } | |
250 | |
176 | 251 /** |
252 * Returns the DocuDirectory indicated by the pathname <code>fn</code>. | |
91 | 253 * |
254 * If <code>fn</code> is a file then its parent directory is returned. | |
255 * | |
176 | 256 * @param fn |
257 * digilib pathname | |
91 | 258 * @return |
259 */ | |
260 public DocuDirectory getDirectory(String fn) { | |
261 DocuDirectory dd; | |
262 // first, assume fn is a directory and look in the cache | |
563 | 263 dd = map.get(fn); |
86 | 264 if (dd == null) { |
265 // cache miss | |
266 misses++; | |
267 // see if it's a directory | |
152 | 268 File f = new File(baseDirNames[0], fn); |
86 | 269 if (f.isDirectory()) { |
151 | 270 dd = new DocuDirectory(fn, this); |
86 | 271 if (dd.isValid()) { |
272 // add to the cache | |
759 | 273 dd = putDir(dd); |
86 | 274 } |
275 } else { | |
276 // maybe it's a file | |
277 if (f.canRead()) { | |
278 // try the parent directory in the cache | |
563 | 279 dd = map.get(f.getParent()); |
86 | 280 if (dd == null) { |
281 // try to read from disk | |
151 | 282 dd = new DocuDirectory(f.getParent(), this); |
86 | 283 if (dd.isValid()) { |
284 // add to the cache | |
759 | 285 dd = putDir(dd); |
86 | 286 } else { |
287 // invalid path | |
288 return null; | |
289 } | |
91 | 290 } else { |
291 // not a real cache miss then | |
292 misses--; | |
86 | 293 } |
99
226624784fe3
Small bug lead to null pointer exception when directory doesn't exist.
robcast
parents:
91
diff
changeset
|
294 } else { |
226624784fe3
Small bug lead to null pointer exception when directory doesn't exist.
robcast
parents:
91
diff
changeset
|
295 // it's not even a file :-( |
226624784fe3
Small bug lead to null pointer exception when directory doesn't exist.
robcast
parents:
91
diff
changeset
|
296 return null; |
86 | 297 } |
298 } | |
299 } else { | |
300 // cache hit | |
301 hits++; | |
302 } | |
303 dd.refresh(); | |
304 if (dd.isValid()) { | |
305 return dd; | |
306 } | |
307 return null; | |
308 } | |
309 | |
310 /** | |
311 * @return String[] | |
312 */ | |
313 public String[] getBaseDirNames() { | |
314 return baseDirNames; | |
315 } | |
316 | |
317 /** | |
318 * @return long | |
319 */ | |
320 public long getNumFiles() { | |
321 return numFiles; | |
322 } | |
323 | |
324 /** | |
325 * Sets the baseDirNames. | |
176 | 326 * |
327 * @param baseDirNames | |
328 * The baseDirNames to set | |
86 | 329 */ |
330 public void setBaseDirNames(String[] baseDirNames) { | |
331 this.baseDirNames = baseDirNames; | |
332 } | |
333 | |
334 /** | |
335 * @return long | |
336 */ | |
337 public long getHits() { | |
338 return hits; | |
339 } | |
340 | |
341 /** | |
342 * @return long | |
343 */ | |
344 public long getMisses() { | |
345 return misses; | |
346 } | |
347 | |
159 | 348 /** |
349 * @return | |
350 */ | |
563 | 351 public FileClass[] getFileClasses() { |
159 | 352 return fileClasses; |
353 } | |
354 | |
355 /** | |
356 * @param fileClasses | |
357 */ | |
563 | 358 public void setFileClasses(FileClass[] fileClasses) { |
159 | 359 this.fileClasses = fileClasses; |
360 } | |
176 | 361 |
86 | 362 } |