Mercurial > hg > digilib-old
comparison servlet/src/digilib/io/DigiDirectory.java @ 339:6d2032b6121d gen2_1
new directory and cache work
author | robcast |
---|---|
date | Wed, 17 Nov 2004 18:17:34 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
3:794a9f25f15c | 339:6d2032b6121d |
---|---|
1 /* DigiDirectory.java -- digilib directory object | |
2 * | |
3 * Digital Image Library servlet components | |
4 * | |
5 * Copyright (C) 2004 Robert Casties (robcast@mail.berlios.de) | |
6 * | |
7 * This program is free software; you can redistribute it and/or modify it | |
8 * under the terms of the GNU General Public License as published by the Free | |
9 * Software Foundation; either version 2 of the License, or (at your option) | |
10 * any later version. | |
11 * | |
12 * Please read license.txt for the full details. A copy of the GPL may be found | |
13 * at http://www.gnu.org/copyleft/lgpl.html | |
14 * | |
15 * You should have received a copy of the GNU General Public License along with | |
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | |
17 * Place, Suite 330, Boston, MA 02111-1307 USA | |
18 * | |
19 * Created on 03.11.2004 | |
20 */ | |
21 package digilib.io; | |
22 | |
23 import java.io.File; | |
24 import java.io.IOException; | |
25 import java.util.Arrays; | |
26 import java.util.Map; | |
27 | |
28 import org.xml.sax.SAXException; | |
29 | |
30 /** | |
31 * digilib directory object | |
32 * | |
33 * @author casties | |
34 * | |
35 */ | |
36 public class DigiDirectory extends DigiDirent { | |
37 | |
38 protected static boolean isFile = false; | |
39 | |
40 protected static boolean isDirectory = true; | |
41 | |
42 protected DigiDirent[] entries; | |
43 | |
44 protected int[][] indexes; | |
45 | |
46 protected File dir; | |
47 | |
48 /** directory name (digilib canonical form) */ | |
49 protected String dlPath = null; | |
50 | |
51 protected long mtime = 0; | |
52 | |
53 protected boolean isDirRead = false; | |
54 | |
55 protected Map unresolvedMeta; | |
56 | |
57 /** | |
58 * @param parent | |
59 * @param dir | |
60 */ | |
61 public DigiDirectory(String dlPath) { | |
62 super(FileOps.dlName(dlPath), null); | |
63 } | |
64 | |
65 /** | |
66 * @param dir | |
67 * @param parent | |
68 */ | |
69 public DigiDirectory(File dir, DigiDirectory parent) { | |
70 super(dir.getName(), parent); | |
71 this.dir = dir; | |
72 this.dlPath = parent.getDLPath() + "/" + dir.getName(); | |
73 } | |
74 | |
75 /** | |
76 * @param dir | |
77 * @param dlpath | |
78 * @param parent | |
79 */ | |
80 public DigiDirectory(File dir, String dlpath, DigiDirectory parent) { | |
81 super(dir.getName(), parent); | |
82 this.dlPath = dlpath; | |
83 this.dir = dir; | |
84 } | |
85 | |
86 public boolean exists() { | |
87 return ((dir != null) && (dir.isDirectory())); | |
88 } | |
89 | |
90 /** | |
91 * Returns the file of the class at the index. | |
92 * | |
93 * @param index | |
94 * @param fc | |
95 * fileClass | |
96 * @return | |
97 */ | |
98 public DigiDirent get(int index, int fc) { | |
99 if (!isDirRead) { | |
100 // read directory now | |
101 if (readDir() < 1) { | |
102 return null; | |
103 } | |
104 } | |
105 try { | |
106 return (DigiDirent) entries[indexes[fc][index]]; | |
107 } catch (Exception e) { | |
108 } | |
109 return null; | |
110 } | |
111 | |
112 /** | |
113 * Returns the file with the name <code>fn</code>. | |
114 * | |
115 * @param fn | |
116 * filename | |
117 * @return | |
118 */ | |
119 public DigiDirent get(String fn) { | |
120 if (!isDirRead) { | |
121 // read directory now | |
122 if (readDir() < 1) { | |
123 return null; | |
124 } | |
125 } | |
126 // search for exact match | |
127 int idx = Arrays.binarySearch(entries, fn); | |
128 if (idx >= 0) { | |
129 return entries[idx]; | |
130 } else { | |
131 // try closest matches without extension | |
132 idx = -idx - 1; | |
133 int imax = entries.length; | |
134 String fb = FileOps.basename(fn); | |
135 if ((idx < imax) | |
136 && (FileOps.basename(entries[idx].getName()).equals(fb))) { | |
137 // idx matches | |
138 return entries[idx]; | |
139 } else if ((idx > 0) | |
140 && (FileOps.basename(entries[idx - 1].getName()).equals(fb))) { | |
141 // idx-1 matches | |
142 return entries[idx - 1]; | |
143 } else if ((idx + 1 < imax) | |
144 && (FileOps.basename(entries[idx + 1].getName()).equals(fb))) { | |
145 // idx+1 matches | |
146 return entries[idx + 1]; | |
147 } | |
148 } | |
149 return null; | |
150 } | |
151 | |
152 | |
153 /** | |
154 * Reads the names of the files in the directory. Fills the filenames array. | |
155 * Returns the number of files. | |
156 * | |
157 * @return | |
158 */ | |
159 public int readDir() { | |
160 if (!exists()) { | |
161 return -1; | |
162 } | |
163 File[] allFiles = null; | |
164 // list all files in the directory | |
165 allFiles = dir.listFiles(); | |
166 if (allFiles == null) { | |
167 // not a directory | |
168 isDirRead = true; | |
169 return -1; | |
170 } | |
171 Arrays.sort(allFiles); | |
172 int nfiles = allFiles.length; | |
173 entries = new DigiDirent[nfiles]; | |
174 // create new index lists for all file classes | |
175 int nfc = FileOps.NUM_CLASSES; | |
176 indexes = new int[nfc][nfiles]; | |
177 // index pointers for the file classes | |
178 int[] lastidx = new int[nfc]; | |
179 Map hints = FileOps.newHints(); | |
180 // go through all files | |
181 for (int dirIdx = 0; dirIdx < nfiles; dirIdx++) { | |
182 File f = allFiles[dirIdx]; | |
183 String fn = f.getName(); | |
184 int fc = FileOps.classForFilename(fn); | |
185 // create the right kind of Dirent | |
186 DigiDirent df = FileOps.fileForClass(fc, f, this, hints); | |
187 // add the file to our list | |
188 entries[dirIdx] = df; | |
189 // add to the indexes | |
190 if (fc >= 0) { | |
191 indexes[fc][lastidx[fc]++] = dirIdx; | |
192 } | |
193 } | |
194 // copy out the index arrays | |
195 for (int i = 0; i < nfc; i++) { | |
196 int[] idxs = new int[lastidx[i]]; | |
197 System.arraycopy(indexes[i], 0, idxs, 0, lastidx[i]); | |
198 indexes[i] = idxs; | |
199 } | |
200 // update modification time | |
201 mtime = dir.lastModified(); | |
202 // read metadata as well | |
203 readMeta(); | |
204 isDirRead = true; | |
205 return nfiles; | |
206 } | |
207 | |
208 /** | |
209 * Check to see if the directory has been modified and reread if necessary. | |
210 * | |
211 * @return boolean the directory is valid | |
212 */ | |
213 public void check() { | |
214 if (isDirRead && (dir.lastModified() > mtime)) { | |
215 // on-disk modification time is more recent | |
216 readDir(); | |
217 } else if (!isDirRead) { | |
218 readDir(); | |
219 } | |
220 } | |
221 | |
222 /** | |
223 * Read directory metadata. | |
224 * | |
225 */ | |
226 public void readMeta() { | |
227 // check for directory metadata... | |
228 File mf = new File(dir, "index.meta"); | |
229 if (mf.canRead()) { | |
230 XMLMetaLoader ml = new XMLMetaLoader(); | |
231 try { | |
232 // read directory meta file | |
233 Map fileMeta = ml.loadURL(mf.getAbsolutePath()); | |
234 if (fileMeta == null) { | |
235 throw new IOException("XMLMetaloader returned no data!"); | |
236 } | |
237 // meta for the directory itself is in the "" bin | |
238 meta = (Map) fileMeta.remove(""); | |
239 // read meta for files in this directory | |
240 storeFileMeta(fileMeta, null); | |
241 // is there meta for other files left? | |
242 if (fileMeta.size() > 0) { | |
243 unresolvedMeta = fileMeta; | |
244 } | |
245 } catch (SAXException e) { | |
246 logger.warn("error parsing index.meta", e); | |
247 } catch (IOException e) { | |
248 logger.warn("error reading index.meta", e); | |
249 } | |
250 } | |
251 readParentMeta(); | |
252 isMetaRead = true; | |
253 } | |
254 | |
255 /** | |
256 * Read metadata from all known parent directories. | |
257 * | |
258 */ | |
259 public void readParentMeta() { | |
260 // check the parent directories for additional file meta | |
261 DigiDirectory dd = getParent(); | |
262 String path = dir.getName(); | |
263 while (dd != null) { | |
264 if (dd.hasUnresolvedMeta()) { | |
265 storeFileMeta(dd.getUnresolvedMeta(), path); | |
266 } | |
267 // prepend parent dir path | |
268 path = dd.getDir().getName() + "/" + path; | |
269 // become next parent | |
270 dd = dd.getParent(); | |
271 } | |
272 } | |
273 | |
274 /** | |
275 * Stores metadata in the files in this directory. | |
276 * | |
277 * Takes a Map with meta-information, adding the relative path before the | |
278 * lookup. | |
279 * | |
280 * @param fileMeta | |
281 * @param relPath | |
282 * @param fc | |
283 * fileClass | |
284 */ | |
285 protected void storeFileMeta(Map fileMeta, String relPath) { | |
286 if (entries == null) { | |
287 // there are no files | |
288 return; | |
289 } | |
290 String path = (relPath != null) ? (relPath + "/") : ""; | |
291 // iterate through the list of files in this directory | |
292 for (int i = 0; i < entries.length; i++) { | |
293 DigiDirent f = entries[i]; | |
294 // prepend path to the filename | |
295 String fn = path + f.getName(); | |
296 // look up meta for this file | |
297 if (relPath == null) { | |
298 // remove from map the same directory | |
299 f.addMeta((Map) fileMeta.remove(fn)); | |
300 } else { | |
301 // copy from map in other directories | |
302 f.addMeta((Map) fileMeta.get(fn)); | |
303 } | |
304 } | |
305 } | |
306 | |
307 /* | |
308 * boring getters and setters | |
309 */ | |
310 | |
311 public boolean hasUnresolvedMeta() { | |
312 return ((unresolvedMeta != null) && unresolvedMeta.isEmpty()); | |
313 } | |
314 | |
315 /** | |
316 * @return Returns the unresolvedMeta. | |
317 */ | |
318 public Map getUnresolvedMeta() { | |
319 return unresolvedMeta; | |
320 } | |
321 | |
322 /** | |
323 * @return Returns the dir. | |
324 */ | |
325 public File getDir() { | |
326 return dir; | |
327 } | |
328 | |
329 /** | |
330 * @param dir | |
331 * The dir to set. | |
332 */ | |
333 public void setDir(File dir) { | |
334 this.dir = dir; | |
335 } | |
336 | |
337 /** | |
338 * @return Returns the dlPath. | |
339 */ | |
340 public String getDLPath() { | |
341 return dlPath; | |
342 } | |
343 | |
344 /** | |
345 * @param dlPath | |
346 * The dlPath to set. | |
347 */ | |
348 public void setDlPath(String dlPath) { | |
349 this.dlPath = dlPath; | |
350 } | |
351 | |
352 /** | |
353 * The number of files in this directory. | |
354 * | |
355 * @return | |
356 */ | |
357 public int getSize() { | |
358 return (entries != null) ? entries.length : 0; | |
359 } | |
360 | |
361 /** | |
362 * The number of files of a file class in this directory. | |
363 * | |
364 * @return | |
365 */ | |
366 public int getSize(int fc) { | |
367 try { | |
368 return indexes[fc].length; | |
369 } catch (Exception e) { | |
370 } | |
371 return 0; | |
372 } | |
373 | |
374 /** | |
375 * @return Returns the mtime. | |
376 */ | |
377 public long getMtime() { | |
378 return mtime; | |
379 } | |
380 } |