Mercurial > hg > digilib-old
view 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 |
line wrap: on
line source
/* DigiDirectory.java -- digilib directory object * * Digital Image Library servlet components * * Copyright (C) 2004 Robert Casties (robcast@mail.berlios.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * Please read license.txt for the full details. A copy of the GPL may be found * at http://www.gnu.org/copyleft/lgpl.html * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA * * Created on 03.11.2004 */ package digilib.io; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Map; import org.xml.sax.SAXException; /** * digilib directory object * * @author casties * */ public class DigiDirectory extends DigiDirent { protected static boolean isFile = false; protected static boolean isDirectory = true; protected DigiDirent[] entries; protected int[][] indexes; protected File dir; /** directory name (digilib canonical form) */ protected String dlPath = null; protected long mtime = 0; protected boolean isDirRead = false; protected Map unresolvedMeta; /** * @param parent * @param dir */ public DigiDirectory(String dlPath) { super(FileOps.dlName(dlPath), null); } /** * @param dir * @param parent */ public DigiDirectory(File dir, DigiDirectory parent) { super(dir.getName(), parent); this.dir = dir; this.dlPath = parent.getDLPath() + "/" + dir.getName(); } /** * @param dir * @param dlpath * @param parent */ public DigiDirectory(File dir, String dlpath, DigiDirectory parent) { super(dir.getName(), parent); this.dlPath = dlpath; this.dir = dir; } public boolean exists() { return ((dir != null) && (dir.isDirectory())); } /** * Returns the file of the class at the index. * * @param index * @param fc * fileClass * @return */ public DigiDirent get(int index, int fc) { if (!isDirRead) { // read directory now if (readDir() < 1) { return null; } } try { return (DigiDirent) entries[indexes[fc][index]]; } catch (Exception e) { } return null; } /** * Returns the file with the name <code>fn</code>. * * @param fn * filename * @return */ public DigiDirent get(String fn) { if (!isDirRead) { // read directory now if (readDir() < 1) { return null; } } // search for exact match int idx = Arrays.binarySearch(entries, fn); if (idx >= 0) { return entries[idx]; } else { // try closest matches without extension idx = -idx - 1; int imax = entries.length; String fb = FileOps.basename(fn); if ((idx < imax) && (FileOps.basename(entries[idx].getName()).equals(fb))) { // idx matches return entries[idx]; } else if ((idx > 0) && (FileOps.basename(entries[idx - 1].getName()).equals(fb))) { // idx-1 matches return entries[idx - 1]; } else if ((idx + 1 < imax) && (FileOps.basename(entries[idx + 1].getName()).equals(fb))) { // idx+1 matches return entries[idx + 1]; } } return null; } /** * Reads the names of the files in the directory. Fills the filenames array. * Returns the number of files. * * @return */ public int readDir() { if (!exists()) { return -1; } File[] allFiles = null; // list all files in the directory allFiles = dir.listFiles(); if (allFiles == null) { // not a directory isDirRead = true; return -1; } Arrays.sort(allFiles); int nfiles = allFiles.length; entries = new DigiDirent[nfiles]; // create new index lists for all file classes int nfc = FileOps.NUM_CLASSES; indexes = new int[nfc][nfiles]; // index pointers for the file classes int[] lastidx = new int[nfc]; Map hints = FileOps.newHints(); // go through all files for (int dirIdx = 0; dirIdx < nfiles; dirIdx++) { File f = allFiles[dirIdx]; String fn = f.getName(); int fc = FileOps.classForFilename(fn); // create the right kind of Dirent DigiDirent df = FileOps.fileForClass(fc, f, this, hints); // add the file to our list entries[dirIdx] = df; // add to the indexes if (fc >= 0) { indexes[fc][lastidx[fc]++] = dirIdx; } } // copy out the index arrays for (int i = 0; i < nfc; i++) { int[] idxs = new int[lastidx[i]]; System.arraycopy(indexes[i], 0, idxs, 0, lastidx[i]); indexes[i] = idxs; } // update modification time mtime = dir.lastModified(); // read metadata as well readMeta(); isDirRead = true; return nfiles; } /** * Check to see if the directory has been modified and reread if necessary. * * @return boolean the directory is valid */ public void check() { if (isDirRead && (dir.lastModified() > mtime)) { // on-disk modification time is more recent readDir(); } else if (!isDirRead) { readDir(); } } /** * Read directory metadata. * */ public void readMeta() { // check for directory metadata... File mf = new File(dir, "index.meta"); if (mf.canRead()) { XMLMetaLoader ml = new XMLMetaLoader(); try { // read directory meta file Map fileMeta = ml.loadURL(mf.getAbsolutePath()); if (fileMeta == null) { throw new IOException("XMLMetaloader returned no data!"); } // meta for the directory itself is in the "" bin meta = (Map) fileMeta.remove(""); // read meta for files in this directory storeFileMeta(fileMeta, null); // is there meta for other files left? if (fileMeta.size() > 0) { unresolvedMeta = fileMeta; } } catch (SAXException e) { logger.warn("error parsing index.meta", e); } catch (IOException e) { logger.warn("error reading index.meta", e); } } readParentMeta(); isMetaRead = true; } /** * Read metadata from all known parent directories. * */ public void readParentMeta() { // check the parent directories for additional file meta DigiDirectory dd = getParent(); String path = dir.getName(); while (dd != null) { if (dd.hasUnresolvedMeta()) { storeFileMeta(dd.getUnresolvedMeta(), path); } // prepend parent dir path path = dd.getDir().getName() + "/" + path; // become next parent dd = dd.getParent(); } } /** * Stores metadata in the files in this directory. * * Takes a Map with meta-information, adding the relative path before the * lookup. * * @param fileMeta * @param relPath * @param fc * fileClass */ protected void storeFileMeta(Map fileMeta, String relPath) { if (entries == null) { // there are no files return; } String path = (relPath != null) ? (relPath + "/") : ""; // iterate through the list of files in this directory for (int i = 0; i < entries.length; i++) { DigiDirent f = entries[i]; // prepend path to the filename String fn = path + f.getName(); // look up meta for this file if (relPath == null) { // remove from map the same directory f.addMeta((Map) fileMeta.remove(fn)); } else { // copy from map in other directories f.addMeta((Map) fileMeta.get(fn)); } } } /* * boring getters and setters */ public boolean hasUnresolvedMeta() { return ((unresolvedMeta != null) && unresolvedMeta.isEmpty()); } /** * @return Returns the unresolvedMeta. */ public Map getUnresolvedMeta() { return unresolvedMeta; } /** * @return Returns the dir. */ public File getDir() { return dir; } /** * @param dir * The dir to set. */ public void setDir(File dir) { this.dir = dir; } /** * @return Returns the dlPath. */ public String getDLPath() { return dlPath; } /** * @param dlPath * The dlPath to set. */ public void setDlPath(String dlPath) { this.dlPath = dlPath; } /** * The number of files in this directory. * * @return */ public int getSize() { return (entries != null) ? entries.length : 0; } /** * The number of files of a file class in this directory. * * @return */ public int getSize(int fc) { try { return indexes[fc].length; } catch (Exception e) { } return 0; } /** * @return Returns the mtime. */ public long getMtime() { return mtime; } }