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