# HG changeset patch # User robcast # Date 1294342949 -3600 # Node ID 69bc69381ac4544028d6ac56585a5097ccd9a095 # Parent 73e041c710d36494f5cc3a9117a89e27d88f811f more work on stream input and more cleanup diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/auth/HashTree.java --- a/servlet/src/digilib/auth/HashTree.java Thu Jan 06 17:33:01 2011 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/* HashTree -- Tree in a Hashtable - - Digital Image Library servlet components - - Copyright (C) 2001, 2002 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 - - */ - -package digilib.auth; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; - -/** - * Tree representation wrapper for a HashMap. - * - * The HashTree is constructed from a HashMap filled with 'branches' with - * 'leaves'. The branches are stored as String keys in the HashMap. The String - * values are leaves. - * - * Branches are matched in 'twigs' separated by 'twig separator' Strings. The - * return values for a match are leaf values separated by 'leaf separator' - * Strings. - * - * @author casties - */ -public class HashTree { - - private Map table; - - private String twigSep = "/"; - - private String leafSep = ","; - - /** - * Constructor of a HashTree. - * - * Creates a HashTree wrapper around a given HashMap, using the given twig - * separator and leaf separator. - * - * @param t - * @param twig_separator - * @param leaf_separator - */ - public HashTree(Map t, String twig_separator, String leaf_separator) { - table = t; - twigSep = twig_separator; - leafSep = leaf_separator; - optimizeTable(); - } - - void optimizeTable() { - } - - /** - * Matches the given branch against the HashTree. - * - * Returns a LinkedList of all leaves on all matching branches in the tree. - * Branches in the tree match if they are substrings starting at the same - * root. - * - * @param branch - * @return - */ - List match(String branch) { - String b = ""; - String m; - LinkedList matches = new LinkedList(); - - // split branch - StringTokenizer twig = new StringTokenizer(branch, twigSep); - // walk branch and check with tree - while (twig.hasMoreTokens()) { - if (b.length() == 0) { - b = twig.nextToken(); - } else { - b += twigSep + twig.nextToken(); - } - m = table.get(b); - if (m != null) { - if (m.indexOf(leafSep) < 0) { - // single leaf - matches.add(m); - } else { - // split leaves - StringTokenizer leaf = new StringTokenizer(m, leafSep); - while (leaf.hasMoreTokens()) { - matches.add(leaf.nextToken()); - } - } - } - } - if (matches.size() > 0) { - return matches; - } else { - return null; - } - } -} diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/auth/XMLAuthOps.java --- a/servlet/src/digilib/auth/XMLAuthOps.java Thu Jan 06 17:33:01 2011 +0100 +++ b/servlet/src/digilib/auth/XMLAuthOps.java Thu Jan 06 20:42:29 2011 +0100 @@ -26,8 +26,9 @@ import javax.servlet.http.HttpServletRequest; -import digilib.io.XMLListLoader; import digilib.servlet.DigilibRequest; +import digilib.util.HashTree; +import digilib.util.XMLListLoader; /** Implementation of AuthOps using XML files. * diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/image/ImageInfoDocuImage.java --- a/servlet/src/digilib/image/ImageInfoDocuImage.java Thu Jan 06 17:33:01 2011 +0100 +++ b/servlet/src/digilib/image/ImageInfoDocuImage.java Thu Jan 06 20:42:29 2011 +0100 @@ -3,7 +3,6 @@ */ package digilib.image; -import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; @@ -18,31 +17,28 @@ */ public abstract class ImageInfoDocuImage extends DocuImageImpl { - /** Check image size and type and store in ImageFile f */ + /* Check image size and type and store in ImageFile f */ public ImageInput identify(ImageInput ii) throws IOException { - // fileset to store the information - File f = ii.getFile(); - if (f == null) { - throw new IOException("File not found!"); - } - RandomAccessFile raf = new RandomAccessFile(f, "r"); + logger.debug("identifying (ImageInfo) " + ii); // set up ImageInfo object ImageInfo iif = new ImageInfo(); - iif.setInput(raf); + if (ii.hasImageInputStream()) { + iif.setInput(ii.getImageInputStream()); + } else if (ii.hasFile()) { + RandomAccessFile raf = new RandomAccessFile(ii.getFile(), "r"); + iif.setInput(raf); + } else { + return null; + } iif.setCollectComments(false); iif.setDetermineImageNumber(false); - logger.debug("identifying (ImageInfo) " + f); // try with ImageInfo first if (iif.check()) { ImageSize d = new ImageSize(iif.getWidth(), iif.getHeight()); ii.setSize(d); ii.setMimetype(iif.getMimeType()); - //logger.debug(" format:"+iif.getFormatName()); - raf.close(); logger.debug("image size: " + ii.getSize()); return ii; - } else { - raf.close(); } return null; } diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/image/ImageLoaderDocuImage.java --- a/servlet/src/digilib/image/ImageLoaderDocuImage.java Thu Jan 06 17:33:01 2011 +0100 +++ b/servlet/src/digilib/image/ImageLoaderDocuImage.java Thu Jan 06 20:42:29 2011 +0100 @@ -29,7 +29,6 @@ import java.awt.image.ConvolveOp; import java.awt.image.Kernel; import java.awt.image.RescaleOp; -import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.RandomAccessFile; @@ -53,7 +52,7 @@ /** Implementation of DocuImage using the ImageLoader API of Java 1.4 and Java2D. */ public class ImageLoaderDocuImage extends ImageInfoDocuImage { - + /** image object */ protected BufferedImage img; @@ -63,9 +62,14 @@ /** ImageIO image reader */ protected ImageReader reader; - /** File that was read */ - protected File imgFile; - + protected static Kernel[] convolutionKernels = { + null, + new Kernel(1, 1, new float[] {1f}), + new Kernel(2, 2, new float[] {0.25f, 0.25f, 0.25f, 0.25f}), + new Kernel(3, 3, new float[] {1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f}) + }; + + /* loadSubimage is supported. */ public boolean isSubimageSupported() { return true; @@ -128,7 +132,12 @@ /* * try ImageReader */ - reader = getReader(input); + try { + reader = getReader(input); + } catch (FileOpException e) { + // maybe just our class doesn't know what to do + return null; + } // set size ImageSize d = new ImageSize(reader.getWidth(0), reader.getHeight(0)); input.setSize(d); @@ -174,7 +183,7 @@ logger.debug("reusing Reader"); return reader; } - // clean up old reader + // clean up old reader (this shouldn't really happen) logger.debug("cleaning Reader!"); dispose(); } @@ -217,9 +226,7 @@ throws FileOpException { logger.debug("loadSubimage"); try { - if ((reader == null) || (imgFile != ii.getFile())) { - getReader(ii); - } + reader = getReader(ii); // set up reader parameters ImageReadParam readParam = reader.getDefaultReadParam(); readParam.setSourceRegion(region); @@ -337,19 +344,23 @@ } public void blur(int radius) throws ImageOpException { - // DEBUG logger.debug("blur: " + radius); // minimum radius is 2 int klen = Math.max(radius, 2); - // FIXME: use constant kernels for most common sizes - int ksize = klen * klen; - // kernel is constant 1/k - float f = 1f / ksize; - float[] kern = new float[ksize]; - for (int i = 0; i < ksize; i++) { - kern[i] = f; + Kernel blur = null; + if (klen < convolutionKernels.length) { + blur = convolutionKernels[klen]; + } else { + // calculate our own kernel + int ksize = klen * klen; + // kernel is constant 1/k + float f = 1f / ksize; + float[] kern = new float[ksize]; + for (int i = 0; i < ksize; ++i) { + kern[i] = f; + } + blur = new Kernel(klen, klen, kern); } - Kernel blur = new Kernel(klen, klen, kern); // blur with convolve operation ConvolveOp blurOp = new ConvolveOp(blur, ConvolveOp.EDGE_NO_OP, renderHint); @@ -415,7 +426,7 @@ /** * Ensures that the array f is in the right order to map the images RGB - * components. (not shure what happens + * components. (not sure what happens otherwise) */ public float[] rgbOrdered(float[] fa) { /* diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/io/AliasingDocuDirCache.java --- a/servlet/src/digilib/io/AliasingDocuDirCache.java Thu Jan 06 17:33:01 2011 +0100 +++ b/servlet/src/digilib/io/AliasingDocuDirCache.java Thu Jan 06 20:42:29 2011 +0100 @@ -28,6 +28,7 @@ import digilib.io.FileOps.FileClass; import digilib.servlet.DigilibConfiguration; +import digilib.util.XMLListLoader; /** * @author casties diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/io/DocuDirectory.java --- a/servlet/src/digilib/io/DocuDirectory.java Thu Jan 06 17:33:01 2011 +0100 +++ b/servlet/src/digilib/io/DocuDirectory.java Thu Jan 06 20:42:29 2011 +0100 @@ -31,6 +31,8 @@ import org.xml.sax.SAXException; import digilib.io.FileOps.FileClass; +import digilib.meta.MetadataMap; +import digilib.meta.XMLMetaLoader; /** * @author casties diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/io/DocuDirent.java --- a/servlet/src/digilib/io/DocuDirent.java Thu Jan 06 17:33:01 2011 +0100 +++ b/servlet/src/digilib/io/DocuDirent.java Thu Jan 06 20:42:29 2011 +0100 @@ -2,6 +2,8 @@ import java.io.File; +import digilib.meta.MetadataMap; + public interface DocuDirent extends Comparable { /** diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/io/DocuDirentImpl.java --- a/servlet/src/digilib/io/DocuDirentImpl.java Thu Jan 06 17:33:01 2011 +0100 +++ b/servlet/src/digilib/io/DocuDirentImpl.java Thu Jan 06 20:42:29 2011 +0100 @@ -28,6 +28,8 @@ import org.apache.log4j.Logger; import digilib.io.FileOps.FileClass; +import digilib.meta.MetadataMap; +import digilib.meta.XMLMetaLoader; /** * Abstract directory entry in a DocuDirectory. diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/io/ImageCacheStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/ImageCacheStream.java Thu Jan 06 20:42:29 2011 +0100 @@ -0,0 +1,49 @@ +/** + * + */ +package digilib.io; + +import java.io.InputStream; + +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.MemoryCacheImageInputStream; + +/** + * @author casties + * + */ +public class ImageCacheStream extends ImageStream { + + public ImageCacheStream(InputStream stream, String mimeType) { + super(stream, mimeType); + } + + /* + * (non-Javadoc) + * + * @see digilib.io.ImageInput#hasImageInputStream() + */ + @Override + public boolean hasImageInputStream() { + return true; + } + + /* + * (non-Javadoc) + * + * @see digilib.io.ImageInput#getImageInputStream() + */ + @Override + public ImageInputStream getImageInputStream() { + /* + * TODO: which type of stream backing? + * In general, it is preferable to + * use a FileCacheImageInputStream when reading from a regular + * InputStream. This class is provided for cases where it is not + * possible to create a writable temporary file. + */ + ImageInputStream iis = new MemoryCacheImageInputStream(this.stream); + return iis; + } + +} diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/io/ImageFile.java --- a/servlet/src/digilib/io/ImageFile.java Thu Jan 06 17:33:01 2011 +0100 +++ b/servlet/src/digilib/io/ImageFile.java Thu Jan 06 20:42:29 2011 +0100 @@ -22,7 +22,12 @@ package digilib.io; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; +import java.io.RandomAccessFile; + +import javax.imageio.stream.FileImageInputStream; +import javax.imageio.stream.ImageInputStream; import digilib.image.ImageSize; import digilib.servlet.DigilibConfiguration; @@ -114,8 +119,39 @@ return name; } - /** - * @return File + + /* (non-Javadoc) + * @see digilib.io.ImageInput#hasImageInputStream() + */ + @Override + public boolean hasImageInputStream() { + return true; + } + + /* (non-Javadoc) + * @see digilib.io.ImageInput#getImageInputStream() + */ + @Override + public ImageInputStream getImageInputStream() { + try { + RandomAccessFile rf = new RandomAccessFile(file, "r"); + return new FileImageInputStream(rf); + } catch (IOException e) { + // what now? + } + return null; + } + + /* (non-Javadoc) + * @see digilib.io.ImageInput#hasFile() + */ + @Override + public boolean hasFile() { + return true; + } + + /* (non-Javadoc) + * @see digilib.io.ImageInput#getFile() */ public File getFile() { return file; diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/io/ImageFileSet.java --- a/servlet/src/digilib/io/ImageFileSet.java Thu Jan 06 17:33:01 2011 +0100 +++ b/servlet/src/digilib/io/ImageFileSet.java Thu Jan 06 20:42:29 2011 +0100 @@ -11,6 +11,8 @@ import org.apache.log4j.Logger; import digilib.io.FileOps.FileClass; +import digilib.meta.MetadataMap; +import digilib.meta.XMLMetaLoader; /** * @author casties diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/io/ImageStream.java --- a/servlet/src/digilib/io/ImageStream.java Thu Jan 06 17:33:01 2011 +0100 +++ b/servlet/src/digilib/io/ImageStream.java Thu Jan 06 20:42:29 2011 +0100 @@ -7,18 +7,35 @@ /** * @author casties - * + * */ public class ImageStream extends ImageInput { - protected InputStream stream = null; - - public ImageStream(InputStream stream, String mimeType) { - this.stream = stream; - this.mimetype = mimeType; - } - - public InputStream getStream() { - return stream; - } + protected InputStream stream = null; + + public ImageStream(InputStream stream, String mimeType) { + this.stream = stream; + this.mimetype = mimeType; + } + + /* + * (non-Javadoc) + * + * @see digilib.io.ImageInput#hasInputStream() + */ + @Override + public boolean hasInputStream() { + return true; + } + + /* + * (non-Javadoc) + * + * @see digilib.io.ImageInput#getInputStream() + */ + @Override + public InputStream getInputStream() { + return stream; + } + } diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/io/MetadataMap.java --- a/servlet/src/digilib/io/MetadataMap.java Thu Jan 06 17:33:01 2011 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -/** - * - */ -package digilib.io; - -import java.util.HashMap; - -/** Map for metadata related to files. - * @author casties - * - */ -@SuppressWarnings("serial") -public class MetadataMap extends HashMap { - -} diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/io/XMLListLoader.java --- a/servlet/src/digilib/io/XMLListLoader.java Thu Jan 06 17:33:01 2011 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,178 +0,0 @@ -/* XMLListLoader -- Load an XML list into a Hashtable - - Digital Image Library servlet components - - Copyright (C) 2001, 2002 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 - -*/ - -package digilib.io; - -// JAXP packages -import java.io.IOException; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.apache.log4j.Logger; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.xml.sax.helpers.DefaultHandler; - -/** Loads a simple XML list into a HashMap. - * - * The XML file has an outer list_tag. Every entry is an - * entry_tag with two attributes: the key_att - * key and the value_att value. - * - * The file is read by the loadURL method, that returns a - * HashMap with the key-value pairs. - * - * @author casties - */ -public class XMLListLoader { - - private Logger logger = Logger.getLogger(this.getClass()); - private String listTag = "list"; - private String entryTag = "entry"; - private String keyAtt = "key"; - private String valueAtt = "value"; - - public XMLListLoader() { - } - - public XMLListLoader( - String list_tag, - String entry_tag, - String key_att, - String value_att) { - logger.debug("xmlListLoader("+list_tag+","+entry_tag+","+key_att+","+value_att+")"); - listTag = list_tag; - entryTag = entry_tag; - keyAtt = key_att; - valueAtt = value_att; - } - - /** - * inner class XMLListParser to be called by the parser - */ - private class XMLListParser extends DefaultHandler { - - private Map listData; - private LinkedList tagSpace; - - public Map getData() { - return listData; - } - - // Parser calls this once at the beginning of a document - public void startDocument() throws SAXException { - listData = new HashMap(); - tagSpace = new LinkedList(); - } - - // Parser calls this for each element in a document - public void startElement( - String namespaceURI, - String localName, - String qName, - Attributes atts) - throws SAXException { - //System.out.println("<"+qName); - // open a new namespace - tagSpace.addLast(qName); - - // ist it an entry tag? - if (qName.equals(entryTag)) { - // is it inside a list tag? - if ((listTag.length() > 0) && (!tagSpace.contains(listTag))) { - logger.error("BOO: Entry " - + entryTag - + " not inside list " - + listTag); - throw new SAXParseException( - "Entry " + entryTag + " not inside list " + listTag, - null); - } - // get the attributes - String key = atts.getValue(keyAtt); - String val = atts.getValue(valueAtt); - if ((key == null) || (val == null)) { - logger.error("BOO: Entry " - + entryTag - + " does not have Attributes " - + keyAtt - + ", " - + valueAtt); - throw new SAXParseException( - "Entry " - + entryTag - + " does not have Attributes " - + keyAtt - + ", " - + valueAtt, - null); - } - // add the values - //System.out.println("DATA: "+key+" = "+val); - listData.put(key, val); - } - } - - public void endElement( - String namespaceURI, - String localName, - String qName) - throws SAXException { - // exit the namespace - tagSpace.removeLast(); - } - - } - - /** - * load and parse a file (as URL) - * returns HashMap with list data - */ - public Map loadURL(String path) throws SAXException, IOException { - //System.out.println("loadurl ("+path+")"); - // Create a JAXP SAXParserFactory and configure it - SAXParserFactory spf = SAXParserFactory.newInstance(); - spf.setNamespaceAware(true); - - SAXParser parser = null; - try { - // Create a JAXP SAXParser - parser = spf.newSAXParser(); - - } catch (ParserConfigurationException e) { - throw new SAXException(e); - } - - // create a list parser (keeps the data!) - XMLListParser listParser = new XMLListParser(); - - // Tell the SAXParser to parse the XML document - parser.parse(path, listParser); - - return listParser.getData(); - } - -} diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/io/XMLMetaLoader.java --- a/servlet/src/digilib/io/XMLMetaLoader.java Thu Jan 06 17:33:01 2011 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,287 +0,0 @@ -/* XMLMetaLoader -- Load an XML format metadata into a Hashtable - - Digital Image Library servlet components - - Copyright (C) 2003 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 - -*/ - -package digilib.io; - -import java.io.IOException; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.apache.log4j.Logger; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -public class XMLMetaLoader { - - private Logger logger = Logger.getLogger(this.getClass()); - private String metaTag = "meta"; - private String fileTag = "file"; - private String fileNameTag = "name"; - private String filePathTag = "path"; - private String imgTag = "img"; - private String collectTag = "context"; - - public XMLMetaLoader() { - } - - /** - * inner class XMLMetaParser to be called by the parser - */ - private class XMLMetaParser extends DefaultHandler { - - private LinkedList tags; - private Map files; - private MetadataMap meta; - private StringBuffer content; - private boolean collecting; - private StringBuffer collectedContent; - private String fileName; - private String filePath; - - /** - * extracts the elements name from either localName ln or qName qn. - * - * @param ln localName - * @param qn qName - * @return element name - */ - private String getName(String ln, String qn) { - if (ln != null) { - if (ln.length() > 0) { - return ln; - } - } - // else it's qName (or nothing) - return qn; - } - - /** - * returns all attributes as a String - * - * @param attrs - * @return - */ - private String getAttrString(Attributes attrs) { - StringBuffer s = new StringBuffer(); - for (int i = 0; i < attrs.getLength(); i++) { - String key = getName(attrs.getLocalName(i), attrs.getQName(i)); - s.append(" "+key+"=\""+attrs.getValue(i)+"\""); - } - return s.toString(); - } - - - // Parser calls this once at the beginning of a document - public void startDocument() throws SAXException { - tags = new LinkedList(); - files = new HashMap(); - collecting = false; - collectedContent = null; - } - - // Parser calls this for each element in a document - public void startElement( - String namespaceURI, - String localName, - String qName, - Attributes atts) - throws SAXException { - - String name = getName(localName, qName); - // open a new tag - tags.addLast(name); - // start new content (no nesting of tags and content) - content = new StringBuffer(); - - if (name.equals(metaTag)) { - // new meta tag - meta = new MetadataMap(); - collectedContent = new StringBuffer(); - } else if (name.equals(fileTag)) { - // new file tag - fileName = null; - filePath = null; - meta = new MetadataMap(); - collectedContent = new StringBuffer(); - } else if (name.equals(collectTag)) { - // start collecting - collecting = true; - if (collectedContent == null) { - collectedContent = new StringBuffer(); - } - } - - // record mode - if (collecting) { - collectedContent.append("<"+name); - collectedContent.append(getAttrString(atts)); - collectedContent.append(">"); - } - } - - // parser calls this for all tag content (possibly more than once) - public void characters(char[] ch, int start, int length) - throws SAXException { - // append data to current string buffer - if (content == null) { - content = new StringBuffer(); - } - content.append(ch, start, length); - } - - // parser calls this at the end of each element - public void endElement( - String namespaceURI, - String localName, - String qName) - throws SAXException { - - String name = getName(localName, qName); - // exit the tag - tags.removeLast(); - String lastTag = (tags.isEmpty()) ? "" : tags.getLast(); - - // was it a file/name tag? - if (name.equals(fileNameTag) && lastTag.equals(fileTag)) { - // save name as filename - if ((content != null) && (content.length() > 0)) { - fileName = content.toString().trim(); - } - content = null; - return; - } - - // was it a file/path tag? - if (name.equals(filePathTag) && lastTag.equals(fileTag)) { - // save path as filepath - if ((content != null) && (content.length() > 0)) { - filePath = content.toString().trim(); - } - content = null; - return; - } - - // was it a file tag? - if (name.equals(fileTag)) { - // is there meta to save? - if ((meta != null) && (meta.size() > 0)) { - // file name is (optional file/path) / file/name - String fn = null; - - if (fileName != null) { - if (filePath != null) { - fn = filePath + "/" + fileName; - } else { - fn = fileName; - } - } else { - // no file name, no file - content = null; - return; - } - // save meta in file list - files.put(fn, meta); - } - content = null; - return; - } - - // was it a meta tag outside a file tag? - if (name.equals(metaTag) && !tags.contains(fileTag)) { - // save meta as dir meta - if ((meta != null) && (meta.size() > 0)) { - files.put("", meta); - } - content = null; - return; - } - - // is this inside an digilib info (=img) tag? - if (lastTag.equals(imgTag)) { - // then add whatever this is - if ((content != null) && (content.length() > 0)) { - meta.put(name, content.toString().trim()); - } - content = null; - return; - } - - // is this the end of collectTag? - if (name.equals(collectTag)) { - collecting = false; - collectedContent.append("\n"); - // store collected stuff - meta.put(collectTag, collectedContent.toString()); - //logger.debug("collected: '"+collectedContent+"'"); - content = null; - return; - } - - // write collected content - if (collecting) { - String s = ""; - if ((content != null) && (content.length() > 0)) { - s = content.toString().trim(); - } - //logger.debug("collect:"+name+" = "+s); - collectedContent.append(s); - collectedContent.append("\n"); - content = null; - return; - } - } - - } - - /** - * load and parse a file (as URL) - * returns HashMap with list data - */ - public Map loadURL(String path) throws SAXException, IOException { - logger.debug("loading meta: "+path); - // Create a JAXP SAXParserFactory and configure it - SAXParserFactory spf = SAXParserFactory.newInstance(); - spf.setNamespaceAware(true); - - SAXParser parser = null; - try { - // Create a JAXP SAXParser - parser = spf.newSAXParser(); - - } catch (ParserConfigurationException e) { - throw new SAXException(e); - } - - // create a list parser (keeps the data!) - XMLMetaParser listParser = new XMLMetaParser(); - - // Tell the SAXParser to parse the XML document - parser.parse(path, listParser); - - return listParser.files; - } - -} diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/meta/MetadataMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/meta/MetadataMap.java Thu Jan 06 20:42:29 2011 +0100 @@ -0,0 +1,15 @@ +/** + * + */ +package digilib.meta; + +import java.util.HashMap; + +/** Map for metadata related to files. + * @author casties + * + */ +@SuppressWarnings("serial") +public class MetadataMap extends HashMap { + +} diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/meta/XMLMetaLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/meta/XMLMetaLoader.java Thu Jan 06 20:42:29 2011 +0100 @@ -0,0 +1,287 @@ +/* XMLMetaLoader -- Load an XML format metadata into a Hashtable + + Digital Image Library servlet components + + Copyright (C) 2003 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 + +*/ + +package digilib.meta; + +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.apache.log4j.Logger; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +public class XMLMetaLoader { + + private Logger logger = Logger.getLogger(this.getClass()); + private String metaTag = "meta"; + private String fileTag = "file"; + private String fileNameTag = "name"; + private String filePathTag = "path"; + private String imgTag = "img"; + private String collectTag = "context"; + + public XMLMetaLoader() { + } + + /** + * inner class XMLMetaParser to be called by the parser + */ + private class XMLMetaParser extends DefaultHandler { + + private LinkedList tags; + private Map files; + private MetadataMap meta; + private StringBuffer content; + private boolean collecting; + private StringBuffer collectedContent; + private String fileName; + private String filePath; + + /** + * extracts the elements name from either localName ln or qName qn. + * + * @param ln localName + * @param qn qName + * @return element name + */ + private String getName(String ln, String qn) { + if (ln != null) { + if (ln.length() > 0) { + return ln; + } + } + // else it's qName (or nothing) + return qn; + } + + /** + * returns all attributes as a String + * + * @param attrs + * @return + */ + private String getAttrString(Attributes attrs) { + StringBuffer s = new StringBuffer(); + for (int i = 0; i < attrs.getLength(); i++) { + String key = getName(attrs.getLocalName(i), attrs.getQName(i)); + s.append(" "+key+"=\""+attrs.getValue(i)+"\""); + } + return s.toString(); + } + + + // Parser calls this once at the beginning of a document + public void startDocument() throws SAXException { + tags = new LinkedList(); + files = new HashMap(); + collecting = false; + collectedContent = null; + } + + // Parser calls this for each element in a document + public void startElement( + String namespaceURI, + String localName, + String qName, + Attributes atts) + throws SAXException { + + String name = getName(localName, qName); + // open a new tag + tags.addLast(name); + // start new content (no nesting of tags and content) + content = new StringBuffer(); + + if (name.equals(metaTag)) { + // new meta tag + meta = new MetadataMap(); + collectedContent = new StringBuffer(); + } else if (name.equals(fileTag)) { + // new file tag + fileName = null; + filePath = null; + meta = new MetadataMap(); + collectedContent = new StringBuffer(); + } else if (name.equals(collectTag)) { + // start collecting + collecting = true; + if (collectedContent == null) { + collectedContent = new StringBuffer(); + } + } + + // record mode + if (collecting) { + collectedContent.append("<"+name); + collectedContent.append(getAttrString(atts)); + collectedContent.append(">"); + } + } + + // parser calls this for all tag content (possibly more than once) + public void characters(char[] ch, int start, int length) + throws SAXException { + // append data to current string buffer + if (content == null) { + content = new StringBuffer(); + } + content.append(ch, start, length); + } + + // parser calls this at the end of each element + public void endElement( + String namespaceURI, + String localName, + String qName) + throws SAXException { + + String name = getName(localName, qName); + // exit the tag + tags.removeLast(); + String lastTag = (tags.isEmpty()) ? "" : tags.getLast(); + + // was it a file/name tag? + if (name.equals(fileNameTag) && lastTag.equals(fileTag)) { + // save name as filename + if ((content != null) && (content.length() > 0)) { + fileName = content.toString().trim(); + } + content = null; + return; + } + + // was it a file/path tag? + if (name.equals(filePathTag) && lastTag.equals(fileTag)) { + // save path as filepath + if ((content != null) && (content.length() > 0)) { + filePath = content.toString().trim(); + } + content = null; + return; + } + + // was it a file tag? + if (name.equals(fileTag)) { + // is there meta to save? + if ((meta != null) && (meta.size() > 0)) { + // file name is (optional file/path) / file/name + String fn = null; + + if (fileName != null) { + if (filePath != null) { + fn = filePath + "/" + fileName; + } else { + fn = fileName; + } + } else { + // no file name, no file + content = null; + return; + } + // save meta in file list + files.put(fn, meta); + } + content = null; + return; + } + + // was it a meta tag outside a file tag? + if (name.equals(metaTag) && !tags.contains(fileTag)) { + // save meta as dir meta + if ((meta != null) && (meta.size() > 0)) { + files.put("", meta); + } + content = null; + return; + } + + // is this inside an digilib info (=img) tag? + if (lastTag.equals(imgTag)) { + // then add whatever this is + if ((content != null) && (content.length() > 0)) { + meta.put(name, content.toString().trim()); + } + content = null; + return; + } + + // is this the end of collectTag? + if (name.equals(collectTag)) { + collecting = false; + collectedContent.append("\n"); + // store collected stuff + meta.put(collectTag, collectedContent.toString()); + //logger.debug("collected: '"+collectedContent+"'"); + content = null; + return; + } + + // write collected content + if (collecting) { + String s = ""; + if ((content != null) && (content.length() > 0)) { + s = content.toString().trim(); + } + //logger.debug("collect:"+name+" = "+s); + collectedContent.append(s); + collectedContent.append("\n"); + content = null; + return; + } + } + + } + + /** + * load and parse a file (as URL) + * returns HashMap with list data + */ + public Map loadURL(String path) throws SAXException, IOException { + logger.debug("loading meta: "+path); + // Create a JAXP SAXParserFactory and configure it + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setNamespaceAware(true); + + SAXParser parser = null; + try { + // Create a JAXP SAXParser + parser = spf.newSAXParser(); + + } catch (ParserConfigurationException e) { + throw new SAXException(e); + } + + // create a list parser (keeps the data!) + XMLMetaParser listParser = new XMLMetaParser(); + + // Tell the SAXParser to parse the XML document + parser.parse(path, listParser); + + return listParser.files; + } + +} diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/servlet/DigilibConfiguration.java --- a/servlet/src/digilib/servlet/DigilibConfiguration.java Thu Jan 06 17:33:01 2011 +0100 +++ b/servlet/src/digilib/servlet/DigilibConfiguration.java Thu Jan 06 20:42:29 2011 +0100 @@ -36,9 +36,9 @@ import digilib.image.DocuImageImpl; import digilib.io.FileOps; import digilib.io.ImageInput; -import digilib.io.XMLListLoader; import digilib.util.Parameter; import digilib.util.ParameterMap; +import digilib.util.XMLListLoader; /** * Class to hold the digilib servlet configuration parameters. The parameters diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/util/HashTree.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/util/HashTree.java Thu Jan 06 20:42:29 2011 +0100 @@ -0,0 +1,113 @@ +/* HashTree -- Tree in a Hashtable + + Digital Image Library servlet components + + Copyright (C) 2001, 2002 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 + + */ + +package digilib.util; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +/** + * Tree representation wrapper for a HashMap. + * + * The HashTree is constructed from a HashMap filled with 'branches' with + * 'leaves'. The branches are stored as String keys in the HashMap. The String + * values are leaves. + * + * Branches are matched in 'twigs' separated by 'twig separator' Strings. The + * return values for a match are leaf values separated by 'leaf separator' + * Strings. + * + * @author casties + */ +public class HashTree { + + private Map table; + + private String twigSep = "/"; + + private String leafSep = ","; + + /** + * Constructor of a HashTree. + * + * Creates a HashTree wrapper around a given HashMap, using the given twig + * separator and leaf separator. + * + * @param t + * @param twig_separator + * @param leaf_separator + */ + public HashTree(Map t, String twig_separator, String leaf_separator) { + table = t; + twigSep = twig_separator; + leafSep = leaf_separator; + optimizeTable(); + } + + private void optimizeTable() { + } + + /** + * Matches the given branch against the HashTree. + * + * Returns a LinkedList of all leaves on all matching branches in the tree. + * Branches in the tree match if they are substrings starting at the same + * root. + * + * @param branch + * @return + */ + public List match(String branch) { + String b = ""; + String m; + LinkedList matches = new LinkedList(); + + // split branch + StringTokenizer twig = new StringTokenizer(branch, twigSep); + // walk branch and check with tree + while (twig.hasMoreTokens()) { + if (b.length() == 0) { + b = twig.nextToken(); + } else { + b += twigSep + twig.nextToken(); + } + m = table.get(b); + if (m != null) { + if (m.indexOf(leafSep) < 0) { + // single leaf + matches.add(m); + } else { + // split leaves + StringTokenizer leaf = new StringTokenizer(m, leafSep); + while (leaf.hasMoreTokens()) { + matches.add(leaf.nextToken()); + } + } + } + } + if (matches.size() > 0) { + return matches; + } else { + return null; + } + } +} diff -r 73e041c710d3 -r 69bc69381ac4 servlet/src/digilib/util/XMLListLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/util/XMLListLoader.java Thu Jan 06 20:42:29 2011 +0100 @@ -0,0 +1,178 @@ +/* XMLListLoader -- Load an XML list into a Hashtable + + Digital Image Library servlet components + + Copyright (C) 2001, 2002 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 + +*/ + +package digilib.util; + +// JAXP packages +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.apache.log4j.Logger; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; + +/** Loads a simple XML list into a HashMap. + * + * The XML file has an outer list_tag. Every entry is an + * entry_tag with two attributes: the key_att + * key and the value_att value. + * + * The file is read by the loadURL method, that returns a + * HashMap with the key-value pairs. + * + * @author casties + */ +public class XMLListLoader { + + private Logger logger = Logger.getLogger(this.getClass()); + private String listTag = "list"; + private String entryTag = "entry"; + private String keyAtt = "key"; + private String valueAtt = "value"; + + public XMLListLoader() { + } + + public XMLListLoader( + String list_tag, + String entry_tag, + String key_att, + String value_att) { + logger.debug("xmlListLoader("+list_tag+","+entry_tag+","+key_att+","+value_att+")"); + listTag = list_tag; + entryTag = entry_tag; + keyAtt = key_att; + valueAtt = value_att; + } + + /** + * inner class XMLListParser to be called by the parser + */ + private class XMLListParser extends DefaultHandler { + + private Map listData; + private LinkedList tagSpace; + + public Map getData() { + return listData; + } + + // Parser calls this once at the beginning of a document + public void startDocument() throws SAXException { + listData = new HashMap(); + tagSpace = new LinkedList(); + } + + // Parser calls this for each element in a document + public void startElement( + String namespaceURI, + String localName, + String qName, + Attributes atts) + throws SAXException { + //System.out.println("<"+qName); + // open a new namespace + tagSpace.addLast(qName); + + // ist it an entry tag? + if (qName.equals(entryTag)) { + // is it inside a list tag? + if ((listTag.length() > 0) && (!tagSpace.contains(listTag))) { + logger.error("BOO: Entry " + + entryTag + + " not inside list " + + listTag); + throw new SAXParseException( + "Entry " + entryTag + " not inside list " + listTag, + null); + } + // get the attributes + String key = atts.getValue(keyAtt); + String val = atts.getValue(valueAtt); + if ((key == null) || (val == null)) { + logger.error("BOO: Entry " + + entryTag + + " does not have Attributes " + + keyAtt + + ", " + + valueAtt); + throw new SAXParseException( + "Entry " + + entryTag + + " does not have Attributes " + + keyAtt + + ", " + + valueAtt, + null); + } + // add the values + //System.out.println("DATA: "+key+" = "+val); + listData.put(key, val); + } + } + + public void endElement( + String namespaceURI, + String localName, + String qName) + throws SAXException { + // exit the namespace + tagSpace.removeLast(); + } + + } + + /** + * load and parse a file (as URL) + * returns HashMap with list data + */ + public Map loadURL(String path) throws SAXException, IOException { + //System.out.println("loadurl ("+path+")"); + // Create a JAXP SAXParserFactory and configure it + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setNamespaceAware(true); + + SAXParser parser = null; + try { + // Create a JAXP SAXParser + parser = spf.newSAXParser(); + + } catch (ParserConfigurationException e) { + throw new SAXException(e); + } + + // create a list parser (keeps the data!) + XMLListParser listParser = new XMLListParser(); + + // Tell the SAXParser to parse the XML document + parser.parse(path, listParser); + + return listParser.getData(); + } + +}