# HG changeset patch # User robcast # Date 1294603863 -3600 # Node ID e8668edcb880eb12467b54df260230429ed70ecf # Parent 7768ea8f59cff326bbdc6c65d653aac5e51b9109# Parent 85e465e6a6425d91c0704f6584a461492d51de97 Merge from HEAD 85e465e6a6425d91c0704f6584a461492d51de97 diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/auth/HashTree.java --- a/servlet/src/digilib/auth/HashTree.java Fri Jan 07 17:47:24 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 85e465e6a642 -r e8668edcb880 servlet/src/digilib/auth/XMLAuthOps.java --- a/servlet/src/digilib/auth/XMLAuthOps.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/auth/XMLAuthOps.java Sun Jan 09 21:11:03 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 85e465e6a642 -r e8668edcb880 servlet/src/digilib/image/DocuImage.java --- a/servlet/src/digilib/image/DocuImage.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/image/DocuImage.java Sun Jan 09 21:11:03 2011 +0100 @@ -27,8 +27,8 @@ import javax.servlet.ServletException; -import digilib.io.ImageFile; import digilib.io.FileOpException; +import digilib.io.ImageInput; /** The basic class for the representation of a digilib image. * @@ -41,12 +41,12 @@ /** Loads an image file into the Object. * - * @param f Image File. + * @param ii Image File. * @throws FileOpException Exception thrown if any error occurs. */ - public void loadImage(ImageFile f) throws FileOpException; + public void loadImage(ImageInput ii) throws FileOpException; - /** This DocuImage support the loadSubImage operation. + /** This DocuImage supports the loadSubImage operation. * * @return boolean */ @@ -54,12 +54,12 @@ /** Load only a subsampled region of the image file. * - * @param f + * @param ii * @param region * @param subsample * @throws FileOpException */ - public void loadSubimage(ImageFile f, Rectangle region, int subsample) + public void loadSubimage(ImageInput ii, Rectangle region, int subsample) throws FileOpException; /** Writes the current image to a ServletResponse. @@ -95,7 +95,7 @@ */ public ImageSize getSize(); - /** The mime-type of the current image. + /** The mime-type of the image, i.e. the mime-type of the input that was read. * * @return String the mime-type of this image. */ @@ -221,9 +221,9 @@ public void dispose(); /** - * Check image size and type and store in ImageFile f + * Check image size and type and store in ImageInput ii */ - public ImageFile identify(ImageFile imgf) throws IOException; + public ImageInput identify(ImageInput ii) throws IOException; /** * Returns a list of supported image formats diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/image/DocuImageImpl.java --- a/servlet/src/digilib/image/DocuImageImpl.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/image/DocuImageImpl.java Sun Jan 09 21:11:03 2011 +0100 @@ -33,7 +33,7 @@ import org.apache.log4j.Logger; import digilib.io.FileOpException; -import digilib.io.ImageFile; +import digilib.io.ImageInput; /** Simple abstract implementation of the DocuImage interface. * @@ -53,13 +53,13 @@ /** epsilon for float comparisons. */ public final double epsilon = 1e-5; - - /** image mime-type */ - protected String mimeType = null; /** image size */ protected ImageSize imgSize = null; + /** ImageInput that was read */ + protected ImageInput input; + /** * Returns the quality. * @return int @@ -99,14 +99,20 @@ scale(scale, scale); } + /* (non-Javadoc) + * @see digilib.image.DocuImage#getMimetype() + */ public String getMimetype() { - return mimeType; + if (input != null) { + return input.getMimetype(); + } + return null; } /* (non-Javadoc) * @see digilib.image.DocuImage#identify(digilib.io.ImageFile) */ - public ImageFile identify(ImageFile imgf) throws IOException { + public ImageInput identify(ImageInput ii) throws IOException { // just a do-nothing implementation return null; } @@ -128,7 +134,7 @@ return false; } - public void loadSubimage(ImageFile f, Rectangle region, int subsample) + public void loadSubimage(ImageInput ii, Rectangle region, int subsample) throws FileOpException { // empty implementation } @@ -177,19 +183,11 @@ return imgSize; } - public void loadImage(ImageFile f) throws FileOpException { - // TODO Auto-generated method stub - - } + public abstract void loadImage(ImageInput ii) throws FileOpException; - public void scale(double scaleX, double scaleY) throws ImageOpException { - // TODO Auto-generated method stub - - } + public abstract void scale(double scaleX, double scaleY) throws ImageOpException; - public void writeImage(String mt, OutputStream ostream) - throws ServletException, ImageOpException { - // TODO Auto-generated method stub - } + public abstract void writeImage(String mt, OutputStream ostream) + throws ServletException, ImageOpException; } diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/image/ImageInfoDocuImage.java --- a/servlet/src/digilib/image/ImageInfoDocuImage.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/image/ImageInfoDocuImage.java Sun Jan 09 21:11:03 2011 +0100 @@ -3,13 +3,12 @@ */ package digilib.image; -import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import org.marcoschmidt.image.ImageInfo; -import digilib.io.ImageFile; +import digilib.io.ImageInput; /** Simple abstract implementation of the DocuImage interface. * Implements only the identify method using the ImageInfo class. @@ -18,31 +17,28 @@ */ public abstract class ImageInfoDocuImage extends DocuImageImpl { - /** Check image size and type and store in ImageFile f */ - public ImageFile identify(ImageFile imgf) throws IOException { - // fileset to store the information - File f = imgf.getFile(); - if (f == null) { - throw new IOException("File not found!"); - } - RandomAccessFile raf = new RandomAccessFile(f, "r"); + /* Check image size and type and store in ImageFile f */ + public ImageInput identify(ImageInput ii) throws IOException { + 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()); - imgf.setSize(d); - imgf.setMimetype(iif.getMimeType()); - //logger.debug(" format:"+iif.getFormatName()); - raf.close(); - logger.debug("image size: " + imgf.getSize()); - return imgf; - } else { - raf.close(); + ii.setSize(d); + ii.setMimetype(iif.getMimeType()); + logger.debug("image size: " + ii.getSize()); + return ii; } return null; } diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/image/ImageJobDescription.java --- a/servlet/src/digilib/image/ImageJobDescription.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/image/ImageJobDescription.java Sun Jan 09 21:11:03 2011 +0100 @@ -11,24 +11,22 @@ import digilib.io.FileOpException; import digilib.io.FileOps; import digilib.io.FileOps.FileClass; -import digilib.io.ImageFile; -import digilib.io.ImageFileset; +import digilib.io.ImageInput; +import digilib.io.ImageSet; import digilib.servlet.DigilibConfiguration; import digilib.util.OptionsSet; import digilib.util.Parameter; import digilib.util.ParameterMap; - -/** - * A container class for storing a set of instructional parameters - * used for content generating classes like MakePDF. +/** + * A class for storing the set of parameters necessary for scaling images + * with an ImageWorker. * - * This contains the functionality formerly found in Scaler, processRequest, only factorized. - * - * TODO clean up... + * This contains the functionality formerly found in Scaler.processRequest(), + * only factorized. * * @author cmielack, casties - * + * */ public class ImageJobDescription extends ParameterMap { @@ -36,18 +34,18 @@ DigilibConfiguration dlConfig = null; protected static Logger logger = Logger.getLogger("digilib.servlet"); - ImageFile fileToLoad = null; - ImageFileset fileset = null; + ImageInput input = null; + ImageSet imageSet = null; DocuDirectory fileDir = null; String filePath = null; ImageSize expectedSourceSize = null; Float scaleXY = null; Rectangle2D userImgArea = null; - Rectangle2D outerUserImgArea= null; + Rectangle2D outerUserImgArea = null; Boolean imageSendable = null; - String mimeType; - Integer paramDW; - Integer paramDH; + String mimeType = null; + Integer paramDW = null; + Integer paramDH = null; /** create empty ImageJobDescription. * @param dlcfg @@ -128,48 +126,56 @@ } + /** Returns the mime-type (of the input). + * @return + * @throws IOException + */ public String getMimeType() throws IOException { if (mimeType == null) { - fileToLoad = getFileToLoad(); - if(! fileToLoad.isChecked()){ - DigilibConfiguration.docuImageIdentify(fileToLoad); - } - mimeType = fileToLoad.getMimetype(); + input = getInput(); + mimeType = input.getMimetype(); } return mimeType; } - public ImageFile getFileToLoad() throws IOException { - - if(fileToLoad == null){ - fileset = getFileset(); + /** Returns the ImageInput to use. + * @return + * @throws IOException + */ + public ImageInput getInput() throws IOException { + if(input == null){ + imageSet = getImageSet(); /* select a resolution */ - if (getHiresOnly()) { + if (isHiresOnly()) { // get first element (= highest resolution) - fileToLoad = fileset.getBiggest(); - } else if (getLoresOnly()) { + input = imageSet.getBiggest(); + } else if (isLoresOnly()) { // enforced lores uses next smaller resolution - fileToLoad = fileset.getNextSmaller(getExpectedSourceSize()); - if (fileToLoad == null) { + input = imageSet.getNextSmaller(getExpectedSourceSize()); + if (input == null) { // this is the smallest we have - fileToLoad = fileset.getSmallest(); + input = imageSet.getSmallest(); } } else { // autores: use next higher resolution - fileToLoad = fileset.getNextBigger(getExpectedSourceSize()); - if (fileToLoad == null) { + input = imageSet.getNextBigger(getExpectedSourceSize()); + if (input == null) { // this is the highest we have - fileToLoad = fileset.getBiggest(); + input = imageSet.getBiggest(); } } - logger.info("Planning to load: " + fileToLoad.getFile()); + logger.info("Planning to load: " + input); } - return fileToLoad; + return input; } + /** Returns the DocuDirectory for the input (file). + * @return + * @throws FileOpException + */ public DocuDirectory getFileDirectory() throws FileOpException { if(fileDir == null){ DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache"); @@ -182,19 +188,26 @@ return fileDir; } - public ImageFileset getFileset() throws FileOpException { - if(fileset==null){ + /** Returns the ImageSet to load. + * @return + * @throws FileOpException + */ + public ImageSet getImageSet() throws FileOpException { + if(imageSet==null){ DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache"); - fileset = (ImageFileset) dirCache.getFile(getFilePath(), getAsInt("pn"), FileClass.IMAGE); - if (fileset == null) { + imageSet = (ImageSet) dirCache.getFile(getFilePath(), getAsInt("pn"), FileClass.IMAGE); + if (imageSet == null) { throw new FileOpException("File " + getFilePath() + "(" + getAsInt("pn") + ") not found."); } } - return fileset; + return imageSet; } + /** Returns the file path name from the request. + * @return + */ public String getFilePath() { if(filePath == null){ String s = this.getAsString("request.path"); @@ -204,32 +217,36 @@ return filePath; } - public boolean getHiresOnly(){ + public boolean isHiresOnly(){ return hasOption("clip") || hasOption("hires"); } - public boolean getLoresOnly(){ + public boolean isLoresOnly(){ return hasOption("lores"); } - public boolean getScaleToFit() { + public boolean isScaleToFit() { return !(hasOption("clip") || hasOption("osize") || hasOption("ascale")); } - public boolean getAbsoluteScale(){ + public boolean isAbsoluteScale(){ return hasOption("osize") || hasOption("ascale"); } + /** Returns the minimum size the source image should have for scaling. + * @return + * @throws IOException + */ public ImageSize getExpectedSourceSize() throws IOException { if (expectedSourceSize == null){ expectedSourceSize = new ImageSize(); - if (getScaleToFit()) { + if (isScaleToFit()) { // scale to fit -- calculate minimum source size float scale = (1 / Math.min(getAsFloat("ww"), getAsFloat("wh"))) * getAsFloat("ws"); expectedSourceSize.setSize((int) (getDw() * scale), (int) (getDh() * scale)); - } else if (getAbsoluteScale() && hasOption("ascale")) { + } else if (isAbsoluteScale() && hasOption("ascale")) { // absolute scale -- apply scale to hires size expectedSourceSize = getHiresSize().getScaled(getAsFloat("scale")); } else { @@ -241,16 +258,17 @@ return expectedSourceSize; } + /** Returns the size of the highest resolution image. + * @return + * @throws IOException + */ public ImageSize getHiresSize() throws IOException { logger.debug("get_hiresSize()"); ImageSize hiresSize = null; - ImageFileset fileset = getFileset(); - if (getAbsoluteScale()) { - ImageFile hiresFile = fileset.getBiggest(); - if (!hiresFile.isChecked()) { - DigilibConfiguration.docuImageIdentify(hiresFile); - } + ImageSet fileset = getImageSet(); + if (isAbsoluteScale()) { + ImageInput hiresFile = fileset.getBiggest(); hiresSize = hiresFile.getSize(); } return hiresSize; @@ -270,7 +288,7 @@ float areaWidth; float areaHeight; float ws = getAsFloat("ws"); - ImageSize imgSize = getFileToLoad().getSize(); + ImageSize imgSize = getInput().getSize(); // user window area in [0,1] coordinates Rectangle2D relUserArea = new Rectangle2D.Float(getAsFloat("wx"), getAsFloat("wy"), getAsFloat("ww"), getAsFloat("wh")); @@ -281,20 +299,20 @@ userImgArea = imgTrafo.createTransformedShape( relUserArea).getBounds2D(); - if (getScaleToFit()) { + if (isScaleToFit()) { // calculate scaling factors based on inner user area areaWidth = (float) userImgArea.getWidth(); areaHeight = (float) userImgArea.getHeight(); float scaleX = getDw() / areaWidth * ws; float scaleY = getDh() / areaHeight * ws; scaleXY = (scaleX > scaleY) ? scaleY : scaleX; - } else if (getAbsoluteScale()) { + } else if (isAbsoluteScale()) { // absolute scaling factor if (hasOption("osize")) { // get original resolution from metadata - fileset.checkMeta(); - float origResX = fileset.getResX(); - float origResY = fileset.getResY(); + imageSet.checkMeta(); + float origResX = imageSet.getResX(); + float origResY = imageSet.getResY(); if ((origResX == 0) || (origResY == 0)) { throw new ImageOpException("Missing image DPI information!"); } @@ -332,6 +350,11 @@ return (float) scaleXY; } + /** Returns the width of the destination image. + * Uses dh parameter and aspect ratio if dw parameter is empty. + * @return + * @throws IOException + */ public int getDw() throws IOException { logger.debug("get_paramDW()"); if (paramDW == null) { @@ -339,7 +362,7 @@ paramDW = getAsInt("dw"); paramDH = getAsInt("dh"); - float imgAspect = getFileToLoad().getAspect(); + float imgAspect = getInput().getAspect(); if (paramDW == 0) { // calculate dw paramDW = Math.round(paramDH * imgAspect); @@ -353,6 +376,11 @@ return paramDW; } + /** Returns the height of the destination image. + * Uses dw parameter and aspect ratio if dh parameter is empty. + * @return + * @throws IOException + */ public int getDh() throws IOException { logger.debug("get_paramDH()"); if (paramDH == null) { @@ -360,7 +388,7 @@ paramDW = getAsInt("dw"); paramDH = getAsInt("dh"); - float imgAspect = getFileToLoad().getAspect(); + float imgAspect = getInput().getAspect(); if (paramDW == 0) { // calculate dw paramDW = Math.round(paramDH * imgAspect); @@ -374,9 +402,12 @@ return paramDH; } - public Integer getScaleQual(){ + /** Returns image quality as an integer. + * @return + */ + public int getScaleQual(){ logger.debug("get_scaleQual()"); - Integer qual = dlConfig.getAsInt("default-quality"); + int qual = dlConfig.getAsInt("default-quality"); if(hasOption("q0")) qual = 0; else if(hasOption("q1")) @@ -387,21 +418,33 @@ } + /** + * Returns the area of the source image that will be transformed into the + * destination image. + * + * @return + * @throws IOException + * @throws ImageOpException + */ public Rectangle2D getUserImgArea() throws IOException, ImageOpException{ if(userImgArea == null) { // getScaleXY sets userImgArea getScaleXY(); } return userImgArea; - } + /** Returns the maximal area of the source image that will be used. + * @return + * @throws IOException + * @throws ImageOpException + */ public Rectangle2D getOuterUserImgArea() throws IOException, ImageOpException { if(outerUserImgArea == null){ outerUserImgArea = getUserImgArea(); // image size in pixels - ImageSize imgSize = getFileToLoad().getSize(); + ImageSize imgSize = getInput().getSize(); Rectangle2D imgBounds = new Rectangle2D.Float(0, 0, imgSize.getWidth(), imgSize.getHeight()); @@ -451,11 +494,13 @@ || hasOption("rawfile"); } - /** Could the image be sent without processing? - * Takes image type and additional image operations into account. - * Does not check requested size transformation. + /** + * Returns if the image can be sent without processing. Takes image type and + * additional image operations into account. Does not check requested size + * transformation. + * * @return - * @throws IOException + * @throws IOException */ public boolean isImageSendable() throws IOException { // cached result? @@ -478,15 +523,22 @@ } + /** + * Returns if any transformation of the source image (image manipulation or + * format conversion) is required. + * + * @return + * @throws IOException + */ public boolean isTransformRequired() throws IOException { - ImageSize is = getFileToLoad().getSize(); + ImageSize is = getInput().getSize(); ImageSize ess = getExpectedSourceSize(); // nt = no transform required boolean nt = isImageSendable() && ( // lores: send if smaller - (getLoresOnly() && is.isSmallerThan(ess)) + (isLoresOnly() && is.isSmallerThan(ess)) // else send if it fits - || (!(getLoresOnly() || getHiresOnly()) && is.fitsIn(ess))); + || (!(isLoresOnly() || isHiresOnly()) && is.fitsIn(ess))); return ! nt; } } \ No newline at end of file diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/image/ImageLoaderDocuImage.java --- a/servlet/src/digilib/image/ImageLoaderDocuImage.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/image/ImageLoaderDocuImage.java Sun Jan 09 21:11:03 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; @@ -49,12 +48,11 @@ import digilib.io.FileOpException; import digilib.io.FileOps; -import digilib.io.ImageFile; -import digilib.io.ImageFileset; +import digilib.io.ImageInput; /** Implementation of DocuImage using the ImageLoader API of Java 1.4 and Java2D. */ public class ImageLoaderDocuImage extends ImageInfoDocuImage { - + /** image object */ protected BufferedImage img; @@ -64,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; @@ -118,44 +121,50 @@ return Arrays.asList(formats).iterator(); } - /** Check image size and type and store in ImageFile f */ - public ImageFile identify(ImageFile imageFile) throws IOException { + /* Check image size and type and store in ImageInput */ + public ImageInput identify(ImageInput input) throws IOException { // try parent method first - ImageFile imf = super.identify(imageFile); - if (imf != null) { - return imf; + ImageInput ii = super.identify(input); + if (ii != null) { + return ii; } - // fileset to store the information - ImageFileset imgfs = imageFile.getParent(); - File f = imageFile.getFile(); - if (f == null) { - throw new IOException("File not found!"); - } - logger.debug("identifying (ImageIO) " + f); + logger.debug("identifying (ImageIO) " + input); /* * try ImageReader */ - if ((reader == null) || (imgFile != imageFile.getFile())) { - getReader(imageFile); + 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)); - imageFile.setSize(d); - // String t = reader.getFormatName(); - String t = FileOps.mimeForFile(f); - imageFile.setMimetype(t); - // logger.debug(" format:"+t); - if (imgfs != null) { - imgfs.setAspect(d); + input.setSize(d); + // set mime type + if (input.getMimetype() == null) { + if (input.hasFile()) { + String t = FileOps.mimeForFile(input.getFile()); + input.setMimetype(t); + } else { + // FIXME: is format name a mime type??? + String t = reader.getFormatName(); + input.setMimetype(t); + } } - return imageFile; + return input; } /* load image file */ - public void loadImage(ImageFile f) throws FileOpException { - logger.debug("loadImage " + f.getFile()); + public void loadImage(ImageInput ii) throws FileOpException { + logger.debug("loadImage: " + ii); + this.input = ii; try { - img = ImageIO.read(f.getFile()); - mimeType = f.getMimetype(); + if (ii.hasImageInputStream()) { + img = ImageIO.read(ii.getImageInputStream()); + } else if (ii.hasFile()) { + img = ImageIO.read(ii.getFile()); + } } catch (IOException e) { throw new FileOpException("Error reading image."); } @@ -166,17 +175,32 @@ * * @return */ - public ImageReader getReader(ImageFile f) throws IOException { - logger.debug("preloadImage " + f.getFile()); - if (reader != null) { - logger.debug("Reader was not null!"); - // clean up old reader + public ImageReader getReader(ImageInput input) throws IOException { + logger.debug("get ImageReader for " + input); + if (this.reader != null) { + if (this.input == input) { + // it was the same input + logger.debug("reusing Reader"); + return reader; + } + // clean up old reader (this shouldn't really happen) + logger.debug("cleaning Reader!"); dispose(); } - RandomAccessFile rf = new RandomAccessFile(f.getFile(), "r"); - ImageInputStream istream = new FileImageInputStream(rf); + this.input = input; + ImageInputStream istream = null; + if (input.hasImageInputStream()) { + // stream input + istream = input.getImageInputStream(); + } else if (input.hasFile()) { + // file only input + RandomAccessFile rf = new RandomAccessFile(input.getFile(), "r"); + istream = new FileImageInputStream(rf); + } else { + throw new FileOpException("Unable to get data from ImageInput"); + } Iterator readers; - String mt = f.getMimetype(); + String mt = input.getMimetype(); if (mt == null) { logger.debug("No mime-type. Trying automagic."); readers = ImageIO.getImageReaders(istream); @@ -185,7 +209,6 @@ readers = ImageIO.getImageReadersByMIMEType(mt); } if (!readers.hasNext()) { - rf.close(); throw new FileOpException("Can't find Reader to load File!"); } reader = readers.next(); @@ -195,18 +218,15 @@ logger.debug("ImageIO: next reader: " + readers.next().getClass()); } */ reader.setInput(istream); - imgFile = f.getFile(); return reader; } /* Load an image file into the Object. */ - public void loadSubimage(ImageFile f, Rectangle region, int prescale) + public void loadSubimage(ImageInput ii, Rectangle region, int prescale) throws FileOpException { logger.debug("loadSubimage"); try { - if ((reader == null) || (imgFile != f.getFile())) { - getReader(f); - } + reader = getReader(ii); // set up reader parameters ImageReadParam readParam = reader.getDefaultReadParam(); readParam.setSourceRegion(region); @@ -216,7 +236,6 @@ // read image logger.debug("loading.."); img = reader.read(0, readParam); - mimeType = f.getMimetype(); logger.debug("loaded"); } catch (IOException e) { throw new FileOpException("Unable to load File!"); @@ -325,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); @@ -403,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 85e465e6a642 -r e8668edcb880 servlet/src/digilib/image/ImageWorker.java --- a/servlet/src/digilib/image/ImageWorker.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/image/ImageWorker.java Sun Jan 09 21:11:03 2011 +0100 @@ -69,19 +69,14 @@ logger.debug("Using subsampling: " + subsamp + " rest " + scaleXY); } - - docuImage.loadSubimage(jobinfo.getFileToLoad(), loadRect, (int) subsamp); - + docuImage.loadSubimage(jobinfo.getInput(), loadRect, (int) subsamp); logger.debug("SUBSAMP: " + subsamp + " -> " + docuImage.getSize()); - docuImage.scale(scaleXY, scaleXY); - } else { // else load and crop the whole file - docuImage.loadImage(jobinfo.getFileToLoad()); + docuImage.loadImage(jobinfo.getInput()); docuImage.crop((int) loadRect.getX(), (int) loadRect.getY(), (int) loadRect.getWidth(), (int) loadRect.getHeight()); - docuImage.scale(scaleXY, scaleXY); } diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/image/JAIDocuImage.java --- a/servlet/src/digilib/image/JAIDocuImage.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/image/JAIDocuImage.java Sun Jan 09 21:11:03 2011 +0100 @@ -24,7 +24,6 @@ import java.awt.RenderingHints; import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; -import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; @@ -46,8 +45,7 @@ import digilib.io.FileOpException; import digilib.io.FileOps; -import digilib.io.ImageFile; -import digilib.io.ImageFileset; +import digilib.io.ImageInput; /** A DocuImage implementation using Java Advanced Imaging Library. */ /** @@ -104,53 +102,64 @@ } /* Check image size and type and store in ImageFile f */ - public ImageFile identify(ImageFile imageFile) throws IOException { + public ImageInput identify(ImageInput input) throws IOException { + this.input = input; // try parent method first - ImageFile imf = super.identify(imageFile); + ImageInput imf = super.identify(input); if (imf != null) { return imf; } - // fileset to store the information - ImageFileset imgfs = imageFile.getParent(); - File f = imageFile.getFile(); - if (f == null) { - throw new IOException("File not found!"); - } /* * try JAI */ - logger.debug("identifying (JAI) " + f); + logger.debug("identifying (JAI) " + input); try { - RenderedOp img = JAI.create("fileload", f.getAbsolutePath()); + RenderedOp img = null; + if (input.hasFile()) { + String t = FileOps.mimeForFile(input.getFile()); + input.setMimetype(t); + img = JAI.create("fileload", input.getFile().getAbsolutePath()); + } else if (input.hasInputStream()) { + img = JAI.create("stream", input.getInputStream()); + // FIXME: where do we get the mimetype? + } else { + throw new FileOpException("unable to get data for image!"); + } ImageSize d = new ImageSize(img.getWidth(), img.getHeight()); - imageFile.setSize(d); - String t = FileOps.mimeForFile(f); - imageFile.setMimetype(t); - // logger.debug(" format:"+t); - if (imgfs != null) { - imgfs.setAspect(d); - } - logger.debug("image size: " + imageFile.getSize()); - return imageFile; + input.setSize(d); + logger.debug("image size: " + d); + return input; } catch (Exception e) { - throw new FileOpException("ERROR: unknown image file format!"); + throw new FileOpException("ERROR: unable to identify image!"); } } /* Load an image file into the Object. */ - public void loadImage(ImageFile f) throws FileOpException { - img = JAI.create("fileload", f.getFile().getAbsolutePath()); + public void loadImage(ImageInput ii) throws FileOpException { + this.input = ii; + if (ii.hasFile()) { + img = JAI.create("fileload", ii.getFile().getAbsolutePath()); + } else if (ii.hasInputStream()) { + img = JAI.create("stream", ii.getInputStream()); + } else { + throw new FileOpException("unable to get data for image!"); + } if (img == null) { throw new FileOpException("Unable to load File!"); } - mimeType = f.getMimetype(); } /* Load an image file into the Object. */ - public void loadSubimage(ImageFile f, Rectangle region, int subsample) - throws FileOpException { + public void loadSubimage(ImageInput ii, Rectangle region, int subsample) throws FileOpException { logger.debug("loadSubimage"); - img = JAI.create("fileload", f.getFile().getAbsolutePath()); + this.input = ii; + if (ii.hasFile()) { + img = JAI.create("fileload", ii.getFile().getAbsolutePath()); + } else if (ii.hasInputStream()) { + img = JAI.create("stream", ii.getInputStream()); + } else { + throw new FileOpException("unable to get data for image!"); + } if ((region.width < img.getWidth()) || (region.height < img.getHeight())) { // setup Crop @@ -174,7 +183,6 @@ // scale logger.debug("loadSubimage: scale"); img = JAI.create("scale", sp); - mimeType = f.getMimetype(); } } diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/image/JAIImageLoaderDocuImage.java --- a/servlet/src/digilib/image/JAIImageLoaderDocuImage.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/image/JAIImageLoaderDocuImage.java Sun Jan 09 21:11:03 2011 +0100 @@ -38,7 +38,7 @@ import javax.servlet.ServletException; import digilib.io.FileOpException; -import digilib.io.ImageFile; +import digilib.io.ImageInput; /** DocuImage implementation using the Java Advanced Imaging API and the ImageLoader * API of Java 1.4. @@ -80,44 +80,73 @@ /* Load an image file into the Object. */ - public void loadImage(ImageFile f) throws FileOpException { - logger.debug("loadImage: "+f.getFile()); - //System.gc(); - img = JAI.create("ImageRead", f.getFile().getAbsolutePath()); + public void loadImage(ImageInput ii) throws FileOpException { + logger.debug("loadImage: "+ii); + if (ii.hasImageInputStream()) { + img = JAI.create("ImageRead", ii.getImageInputStream()); + } else if (ii.hasFile()) { + img = JAI.create("ImageRead", ii.getFile().getAbsolutePath()); + } if (img == null) { throw new FileOpException("Unable to load File!"); } - mimeType = f.getMimetype(); } /* Get an ImageReader for the image file. */ - public ImageReader getReader(ImageFile f) throws IOException { - logger.debug("preloadImage: "+f.getFile()); - //System.gc(); - RandomAccessFile rf = new RandomAccessFile(f.getFile(), "r"); - ImageInputStream istream = new FileImageInputStream(rf); - //Iterator readers = ImageIO.getImageReaders(istream); - Iterator readers = ImageIO.getImageReadersByMIMEType(f.getMimetype()); - if (! readers.hasNext()) { - throw new FileOpException("Unable to load File!"); - } - reader = readers.next(); - logger.debug("JAIImageIO: this reader: " + reader.getClass()); - while (readers.hasNext()) { - logger.debug(" next reader: " + readers.next().getClass()); - } - reader.setInput(istream); - return reader; + public ImageReader getReader(ImageInput input) throws IOException { + logger.debug("get ImageReader for " + input); + if (this.reader != null) { + if (this.input == input) { + // it was the same input + logger.debug("reusing Reader"); + return reader; + } + // clean up old reader + logger.debug("cleaning Reader!"); + dispose(); + } + this.input = input; + ImageInputStream istream = null; + if (input.hasImageInputStream()) { + // stream input + istream = input.getImageInputStream(); + } else if (input.hasFile()) { + // file only input + RandomAccessFile rf = new RandomAccessFile(input.getFile(), "r"); + istream = new FileImageInputStream(rf); + } else { + throw new FileOpException("Unable to get data from ImageInput"); + } + Iterator readers; + String mt = input.getMimetype(); + if (mt == null) { + logger.debug("No mime-type. Trying automagic."); + readers = ImageIO.getImageReaders(istream); + } else { + logger.debug("File type:" + mt); + readers = ImageIO.getImageReadersByMIMEType(mt); + } + if (!readers.hasNext()) { + throw new FileOpException("Can't find Reader to load File!"); + } + reader = readers.next(); + logger.debug("ImageIO: this reader: " + reader.getClass()); + /* are there more readers? */ + /* while (readers.hasNext()) { + logger.debug("ImageIO: next reader: " + readers.next().getClass()); + } */ + reader.setInput(istream); + return reader; } /* Load an image file into the Object. */ - public void loadSubimage(ImageFile f, Rectangle region, int prescale) + public void loadSubimage(ImageInput ii, Rectangle region, int prescale) throws FileOpException { - logger.debug("loadSubimage: "+f.getFile()); + logger.debug("loadSubimage: "+ii.getFile()); //System.gc(); try { - if ((reader == null) || (imgFile != f.getFile())) { - getReader(f); + if ((reader == null) || (imgFile != ii.getFile())) { + getReader(ii); } ImageReadParam readParam = reader.getDefaultReadParam(); readParam.setSourceRegion(region); @@ -137,8 +166,7 @@ if (img == null) { throw new FileOpException("Unable to load File!"); } - imgFile = f.getFile(); - mimeType = f.getMimetype(); + imgFile = ii.getFile(); } diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/AliasingDocuDirCache.java --- a/servlet/src/digilib/io/AliasingDocuDirCache.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/io/AliasingDocuDirCache.java Sun Jan 09 21:11:03 2011 +0100 @@ -28,6 +28,7 @@ import digilib.io.FileOps.FileClass; import digilib.servlet.DigilibConfiguration; +import digilib.util.XMLListLoader; /** * @author casties diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/DigilibInfoReader.java --- a/servlet/src/digilib/io/DigilibInfoReader.java Fri Jan 07 17:47:24 2011 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -package digilib.io; - -/** DigilibInfoReader - * A class for reading the information from info.xml files used in digilib image directories. - * - */ - -import java.io.File; -import java.util.List; - -import org.apache.log4j.Logger; -import org.jdom.Document; -import org.jdom.Element; -import org.jdom.input.SAXBuilder; - - - -public class DigilibInfoReader { - - /** gengeral logger for this class */ - protected static Logger logger = Logger.getLogger("digilib.servlet"); - - private String filename = null; - //private static String base_element = "info"; - - public DigilibInfoReader(String fn){ - filename = fn; - } - - /** - * Returns the attribute defined by 'attr' as a String. - * - * @param attr - * @return - */ - @SuppressWarnings("unchecked") // Element.getChildren() returns naked List - public String getAsString(String attr){ - try{ - SAXBuilder builder = new SAXBuilder(); - Document doc = builder.build(new File(filename)); - Element root = doc.getRootElement(); - List mainElements = root.getChildren(); - // logger.debug("XML mainElements:"+mainElements.toString()); - - for(int i=0; i> list = null; - /** default FileClass for unspecified calls */ - public static FileClass defaultFileClass = FileClass.IMAGE; - /** directory object is valid (exists on disk) */ private boolean isValid = false; @@ -52,6 +51,9 @@ /** directory name (digilib canonical form) */ private String dirName = null; + /** array of parallel dirs for scaled images */ + private Directory[] dirs = null; + /** directory metadata */ private MetadataMap dirMeta = null; @@ -111,7 +113,7 @@ * */ public int size() { - return size(defaultFileClass); + return ((list != null) && (list.get(0) != null)) ? list.get(0).size() : 0; } /** @@ -121,13 +123,7 @@ * fileClass */ public int size(FileClass fc) { - if (list != null) { - List l = list.get(fc.ordinal()); - if (l != null) { - return l.size(); - } - } - return 0; + return ((list != null) && (list.get(fc.ordinal()) != null)) ? list.get(fc.ordinal()).size() : 0; } /** @@ -136,8 +132,11 @@ * @param index * @return */ - public ImageFileset get(int index) { - return (ImageFileset) get(index, defaultFileClass); + public DocuDirent get(int index) { + if ((list == null) || (list.get(0) == null) || (index >= list.get(0).size())) { + return null; + } + return list.get(0).get(index); } /** @@ -177,81 +176,75 @@ * * @return boolean the directory exists */ - public synchronized boolean readDir() { + public boolean readDir() { // check directory first checkDir(); if (!isValid) { return false; } - // first file extension to try for scaled directories - String scalext = null; // read all filenames logger.debug("reading directory " + dir.getPath()); + File[] allFiles = null; /* * using ReadableFileFilter is safer (we won't get directories with file * extensions) but slower. */ - File[] allFiles = null; - // allFiles = dir.listFiles(new FileOps.ReadableFileFilter()); + // allFiles = dir.listFiles(new FileOps.ReadableFileFilter()); allFiles = dir.listFiles(); - //logger.debug(" done"); if (allFiles == null) { // not a directory return false; } - // list of base dirs from the parent cache - String[] baseDirNames = cache.getBaseDirNames(); - // number of base dirs - int nb = baseDirNames.length; - // array of base dirs - Directory[] dirs = new Directory[nb]; - // first entry is this directory - dirs[0] = this; - // fill array with the remaining directories - for (int j = 1; j < nb; j++) { - File d = new File(baseDirNames[j], dirName); - if (d.isDirectory()) { - dirs[j] = new Directory(d); - logger.debug(" reading scaled directory " + d.getPath()); - dirs[j].readDir(); - //logger.debug(" done"); + // init parallel directories + if (dirs == null) { + // list of base dirs from the parent cache + String[] baseDirNames = cache.getBaseDirNames(); + // number of base dirs + int nb = baseDirNames.length; + // array of parallel dirs + dirs = new Directory[nb]; + // first entry is this directory + dirs[0] = this; + // fill array with the remaining directories + for (int j = 1; j < nb; j++) { + // add dirName to baseDirName + File d = new File(baseDirNames[j], dirName); + if (d.isDirectory()) { + dirs[j] = new Directory(d); + logger.debug(" reading scaled directory " + d.getPath()); + dirs[j].readDir(); + } } } // go through all file classes - //for (int classIdx = 0; classIdx < FileOps.NUM_CLASSES; classIdx++) { - for (FileClass fileClass: cache.getFileClasses()) { - //fileClass = cache.getFileClasses()[classIdx]; - File[] fileList = FileOps.listFiles(allFiles, FileOps - .filterForClass(fileClass)); - //logger.debug(" done"); + for (FileClass fileClass : cache.getFileClasses()) { + File[] fileList = FileOps.listFiles(allFiles, + FileOps.filterForClass(fileClass)); // number of files in the directory int numFiles = fileList.length; if (numFiles > 0) { // create new list - list.set(fileClass.ordinal(), new ArrayList(numFiles)); - // sort the file names alphabetically and iterate the list - // Arrays.sort(fileList); // not needed - Map hints = FileOps.newHints(FileOps.HINT_BASEDIRS, dirs); - hints.put(FileOps.HINT_FILEEXT, scalext); - for (int i = 0; i < numFiles; i++) { - DocuDirent f = FileOps.fileForClass(fileClass, fileList[i], - hints); + ArrayList dl = new ArrayList(numFiles); + list.set(fileClass.ordinal(), dl); + for (File f : fileList) { + DocuDirent df = FileOps.fileForClass(fileClass, f, dirs); + df.setParent(this); // add the file to our list - // logger.debug(f.getName()); - - list.get(fileClass.ordinal()).add(f); - f.setParent(this); + dl.add(df); } - // we sort the inner ArrayList (the list of files not the list of file types) - // for binarySearch to work (DocuDirent's natural sort order is by filename) - Collections.sort(list.get(fileClass.ordinal())); + /* + * we sort the inner ArrayList (the list of files not the list + * of file types) for binarySearch to work (DocuDirent's natural + * sort order is by filename) + */ + Collections.sort(dl); } } // clear the scaled directories - for (int j = 1; j < nb; j++) { - if (dirs[j] != null) { - dirs[j].clearFilenames(); + for (Directory d: dirs) { + if (d != null) { + d.clearFilenames(); } } // update number of cached files if this was the first time @@ -456,9 +449,8 @@ return -1; } - private boolean isBasenameInList(List fl, int idx, String fn) { - String dfn = FileOps.basename((fl.get(idx)) - .getName()); + private boolean isBasenameInList(List fileList, int idx, String fn) { + String dfn = FileOps.basename((fileList.get(idx)).getName()); return (dfn.equals(fn)||dfn.equals(FileOps.basename(fn))); } @@ -474,7 +466,12 @@ * @return DocuDirent */ public DocuDirent find(String fn) { - return find(fn, defaultFileClass); + FileClass fc = FileOps.classForFilename(fn); + int i = indexOf(fn, fc); + if (i >= 0) { + return list.get(0).get(i); + } + return null; } /** @@ -491,7 +488,7 @@ public DocuDirent find(String fn, FileClass fc) { int i = indexOf(fn, fc); if (i >= 0) { - return (DocuDirent) list.get(fc.ordinal()).get(i); + return list.get(fc.ordinal()).get(i); } return null; } diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/DocuDirent.java --- a/servlet/src/digilib/io/DocuDirent.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/io/DocuDirent.java Sun Jan 09 21:11:03 2011 +0100 @@ -1,169 +1,81 @@ -/* - * DocuDirent.java -- Abstract directory entry in a DocuDirectory - * - * 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 - * - * Created on 15.09.2003 by casties - * - */ package digilib.io; import java.io.File; -import java.util.Map; - -import org.apache.log4j.Logger; - -import digilib.io.FileOps.FileClass; -/** - * Abstract directory entry in a DocuDirectory. - * - * @author casties - * - */ -public abstract class DocuDirent implements Comparable { +import digilib.meta.MetadataMap; + +public interface DocuDirent extends Comparable { - /** the file class of this file */ - protected static FileClass fileClass = FileClass.NONE; - /** HashMap with metadata */ - protected MetadataMap fileMeta = null; - /** Is the Metadata valid */ - protected boolean metaChecked = false; - /** the parent directory */ - protected Directory parent = null; - - /** - * Checks metadata and does something with it. - * - */ - public abstract void checkMeta(); + /** + * Checks metadata and does something with it. + * + */ + public abstract void checkMeta(); - /** - * gets the (default) File - * - * @return - */ - public abstract File getFile(); + /** + * gets the (default) File + * + * @return + */ + public abstract File getFile(); - /** - * Reads meta-data for this Fileset if there is any. - * - */ - public void readMeta() { - if ((fileMeta != null) || (getFile() == null)) { - // there is already metadata or there is no file - return; - } - // metadata is in the file {filename}.meta - String fn = getFile().getAbsolutePath(); - File mf = new File(fn + ".meta"); - if (mf.canRead()) { - XMLMetaLoader ml = new XMLMetaLoader(); - try { - // read meta file - Map meta = ml.loadURL(mf.getAbsolutePath()); - if (meta == null) { - return; - } - fileMeta = meta.get(getName()); - } catch (Exception e) { - Logger.getLogger(this.getClass()).warn("error reading file .meta", e); - } - } - } + /** + * Reads meta-data for this Fileset if there is any. + * + */ + public abstract void readMeta(); + + /** + * The name of the file. + * + * If this is a Fileset, the method returns the name of the default file + * (for image filesets the highest resolution file). + * + * @return + */ + public abstract String getName(); - /** - * The name of the file. - * - * If this is a Fileset, the method returns the name of the default file - * (for image filesets the highest resolution file). - * - * @return - */ - public String getName() { - File f = getFile(); - return (f != null) ? f.getName() : null; - } - - /** - * Returns the parent Directory. - * - * @return DocuDirectory - */ - public Directory getParent() { - return parent; - } - - /** - * Sets the parent Directory. - * - * @param parent - * The parent to set - */ - public void setParent(Directory parent) { - this.parent = parent; - } - - /** - * Returns the meta-data for this file(set). - * - * @return HashMap - */ - public MetadataMap getFileMeta() { - return fileMeta; - } - - /** - * Sets the meta-data for this file(set) . - * - * @param fileMeta - * The fileMeta to set - */ - public void setFileMeta(MetadataMap fileMeta) { - this.fileMeta = fileMeta; - } - - /** - * @return - */ - public boolean isMetaChecked() { - return metaChecked; - } - - /** - * @return - */ - public static FileClass getFileClass() { - return fileClass; - } + /** + * Returns the parent Directory. + * + * @return DocuDirectory + */ + public abstract Directory getParent(); + + /** + * Sets the parent Directory. + * + * @param parent + * The parent to set + */ + public abstract void setParent(Directory parent); + + /** + * Returns the meta-data for this file(set). + * + * @return HashMap + */ + public abstract MetadataMap getFileMeta(); - /** Comparator using the file name. - * Compares to a String (for binarySearch) + /** + * Sets the meta-data for this file(set) . + * + * @param fileMeta + * The fileMeta to set + */ + public abstract void setFileMeta(MetadataMap fileMeta); + + /** + * @return + */ + public abstract boolean isMetaChecked(); + + /** Comparator using the file name. + * Compares to a String (for binarySearch) * or to another DocuDirent (for sort) - * - * @see java.lang.Comparable#compareTo(java.lang.Object) - */ - public int compareTo(Object arg0) { - if (arg0 instanceof DocuDirent) { - return getName().compareTo(((DocuDirent) arg0).getName()); - } else { - return getName().compareTo((String) arg0); - } - } + * + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public abstract int compareTo(Object arg0); - -} +} \ No newline at end of file diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/DocuDirentImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/DocuDirentImpl.java Sun Jan 09 21:11:03 2011 +0100 @@ -0,0 +1,149 @@ +/* + * DocuDirent.java -- Abstract directory entry in a DocuDirectory + * + * 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 + * + * Created on 15.09.2003 by casties + * + */ +package digilib.io; + +import java.io.File; +import java.util.Map; + +import org.apache.log4j.Logger; + +import digilib.io.FileOps.FileClass; +import digilib.meta.MetadataMap; +import digilib.meta.XMLMetaLoader; + +/** + * Abstract directory entry in a DocuDirectory. + * + * @author casties + * + */ +public abstract class DocuDirentImpl implements DocuDirent { + + /** the file class of this file */ + protected static FileClass fileClass = FileClass.NONE; + /** HashMap with metadata */ + protected MetadataMap fileMeta = null; + /** Is the Metadata valid */ + protected boolean metaChecked = false; + /** the parent directory */ + protected Directory parent = null; + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#checkMeta() + */ + public abstract void checkMeta(); + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#getInput() + */ + public abstract File getFile(); + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#readMeta() + */ + public void readMeta() { + if ((fileMeta != null) || (getFile() == null)) { + // there is already metadata or there is no file + return; + } + // metadata is in the file {filename}.meta + String fn = getFile().getAbsolutePath(); + File mf = new File(fn + ".meta"); + if (mf.canRead()) { + XMLMetaLoader ml = new XMLMetaLoader(); + try { + // read meta file + Map meta = ml.loadURL(mf.getAbsolutePath()); + if (meta == null) { + return; + } + fileMeta = meta.get(getName()); + } catch (Exception e) { + Logger.getLogger(this.getClass()).warn("error reading file .meta", e); + } + } + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#getName() + */ + public String getName() { + File f = getFile(); + return (f != null) ? f.getName() : null; + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#getParent() + */ + public Directory getParent() { + return parent; + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#setParent(digilib.io.Directory) + */ + public void setParent(Directory parent) { + this.parent = parent; + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#getFileMeta() + */ + public MetadataMap getFileMeta() { + return fileMeta; + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#setFileMeta(digilib.io.MetadataMap) + */ + public void setFileMeta(MetadataMap fileMeta) { + this.fileMeta = fileMeta; + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#isMetaChecked() + */ + public boolean isMetaChecked() { + return metaChecked; + } + + /** + * @return + */ + public static FileClass getFileClass() { + return fileClass; + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#compareTo(java.lang.Object) + */ + public int compareTo(Object arg0) { + if (arg0 instanceof DocuDirentImpl) { + return getName().compareTo(((DocuDirent) arg0).getName()); + } else { + return getName().compareTo((String) arg0); + } + } + + +} diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/FileOps.java --- a/servlet/src/digilib/io/FileOps.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/io/FileOps.java Sun Jan 09 21:11:03 2011 +0100 @@ -329,20 +329,20 @@ /** * Factory for DocuDirents based on file class. * - * Returns an ImageFileset, TextFile or SVGFile. baseDirs and scalext are + * Returns an ImageSet, TextFile or SVGFile. scaleDirs are * only for ImageFilesets. * * @param fileClass * @param file - * @param hints + * @param scaleDirs * optional additional parameters * @return */ - public static DocuDirent fileForClass(FileClass fileClass, File file, Map hints) { + public static DocuDirent fileForClass(FileClass fileClass, File file, Directory[] scaleDirs) { // what class of file do we have? if (fileClass == FileClass.IMAGE) { // image file - return new ImageFileset(file, hints); + return new ImageFileSet(file, scaleDirs); } else if (fileClass == FileClass.TEXT) { // text file return new TextFile(file); diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/ImageCacheStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/ImageCacheStream.java Sun Jan 09 21:11:03 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 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/ImageFile.java --- a/servlet/src/digilib/io/ImageFile.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/io/ImageFile.java Sun Jan 09 21:11:03 2011 +0100 @@ -22,74 +22,143 @@ 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; /** * @author casties */ -public class ImageFile { +public class ImageFile extends ImageInput { + // file + private File file = null; // file name - private String filename = null; - // parent ImageFileset - private ImageFileset parent = null; + private String name = null; // parent directory private Directory dir = null; - // mime file type - private String mimetype = null; - // image size in pixels - private ImageSize pixelSize = null; - public ImageFile(String fn, ImageFileset parent, Directory dir) { - this.filename = fn; + /** Constructor with File. + * + * @param f + * @param parent + * @param dir + */ + public ImageFile(File f, ImageSet parent, Directory dir) { + this.file = f; + this.name = f.getName(); this.parent = parent; this.dir = dir; } - public ImageFile(String fn) { - File f = new File(fn); - this.dir = new Directory(f.getParentFile()); - this.filename = f.getName(); + /** Constructor with filename (without path). + * @param fn + * @param parent + * @param dir + */ + public ImageFile(String fn, ImageSet parent, Directory dir) { + this.name = fn; + this.dir = dir; + this.file = new File(this.dir.getDir(), fn); + this.parent = parent; + } + + + /** Checks the image and sets size and type. + * + */ + public void check() { + if (pixelSize == null) { + try { + // use the configured toolkit to identify the image + DigilibConfiguration.identifyDocuImage(this); + } catch (IOException e) { + // nothing much to do... + } + } } - /** Returns the file name (without path). + /* (non-Javadoc) + * @see digilib.io.ImageInput#getSize() + */ + @Override + public ImageSize getSize() { + check(); + return pixelSize; + } + + /* (non-Javadoc) + * @see digilib.io.ImageInput#getMimetype() + */ + @Override + public String getMimetype() { + check(); + return mimetype; + } + + /* (non-Javadoc) + * @see digilib.io.ImageInput#getAspect() + */ + @Override + public float getAspect() { + check(); + return (pixelSize != null) ? pixelSize.getAspect() : 0f; + } + + /** Returns the file name (without path). * * @return */ public String getName() { - return filename; - } - - - /** - * @return File - */ - public File getFile() { - if (dir == null) { - return null; - } - File f = new File(dir.getDir(), filename); - return f; + return name; } - /** - * @return ImageSize + + /* (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 ImageSize getSize() { - return pixelSize; + public File getFile() { + return file; } - /** - * @return String - */ - public String getMimetype() { - return mimetype; - } - - /** - * Sets the imageSize. - * @param imageSize The imageSize to set + /* (non-Javadoc) + * @see digilib.io.ImageInput#setSize(digilib.image.ImageSize) */ public void setSize(ImageSize imageSize) { this.pixelSize = imageSize; @@ -99,42 +168,17 @@ } } - /** - * Sets the mimetype. - * @param mimetype The mimetype to set - */ - public void setMimetype(String filetype) { - this.mimetype = filetype; - } - - /** - * @return ImageFileset - */ - public ImageFileset getParent() { - return parent; - } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + // try to use File.toString + if (file != null) { + return file.toString(); + } + return super.toString(); + } - /** - * Sets the parent. - * @param parent The parent to set - */ - public void setParent(ImageFileset parent) { - this.parent = parent; - } - - /** - * @return boolean - */ - public boolean isChecked() { - return (pixelSize != null); - } - /** Returns the aspect ratio of the image (width/height). - * - * @return - */ - public float getAspect() { - return (pixelSize != null) ? pixelSize.getAspect() : 0; - } - } diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/ImageFileSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/ImageFileSet.java Sun Jan 09 21:11:03 2011 +0100 @@ -0,0 +1,307 @@ +/** + * + */ +package digilib.io; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; + +import org.apache.log4j.Logger; + +import digilib.io.FileOps.FileClass; +import digilib.meta.MetadataMap; +import digilib.meta.XMLMetaLoader; + +/** + * @author casties + * + */ +public class ImageFileSet extends ImageSet implements DocuDirent { + + /** this is an image file */ + protected static FileClass fileClass = FileClass.IMAGE; + /** the (main) file */ + protected File file = null; + /** the file name */ + protected String name = null; + /** HashMap with metadata */ + protected MetadataMap fileMeta = null; + /** Is the Metadata valid */ + protected boolean metaChecked = false; + /** the parent directory */ + protected Directory parentDir = null; + + /** + * Constructor with a File and Directories. + * + * @param file + * @param scaleDirs + */ + public ImageFileSet(File file, Directory[] scaleDirs) { + int nb = scaleDirs.length; + list = new ArrayList(nb); + // first dir is our parent + parentDir = scaleDirs[0]; + this.file = file; + this.name = file.getName(); + fill(scaleDirs, file); + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#getName() + */ + public String getName() { + return this.name; + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#getParent() + */ + public Directory getParent() { + return this.parentDir; + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#setParent(digilib.io.Directory) + */ + public void setParent(Directory parent) { + this.parentDir = parent; + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#getFileMeta() + */ + public MetadataMap getFileMeta() { + return this.fileMeta; + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#setFileMeta(digilib.io.MetadataMap) + */ + public void setFileMeta(MetadataMap fileMeta) { + this.fileMeta = fileMeta; + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#isMetaChecked() + */ + public boolean isMetaChecked() { + return this.metaChecked; + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#compareTo(java.lang.Object) + */ + public int compareTo(Object arg0) { + if (arg0 instanceof DocuDirent) { + return name.compareTo(((DocuDirent) arg0).getName()); + } else { + return getName().compareTo((String) arg0); + } + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#getFile() + */ + public File getFile() { + return file; + } + + /** + * Adds an ImageFile to this Fileset. + * + * The files should be added in the order of higher to lower resolutions. + * The first file is considered the hires "original". + * + * + * @param f + * file to add + * @return true (always) + */ + public boolean add(ImageInput f) { + f.setParent(this); + return list.add(f); + } + + /** + * Fill the ImageSet with files from different base directories. + * + * + * @param dirs + * list of base directories + * @param fl + * file (from first base dir) + * @param hints + * + */ + void fill(Directory[] dirs, File fl) { + String fn = fl.getName(); + String baseFn = FileOps.basename(fn); + // add the first ImageFile to the ImageSet + add(new ImageFile(fl, this, parentDir)); + // iterate the remaining base directories + for (int i = 1; i < dirs.length; ++i) { + Directory dir = dirs[i]; + if (dir == null) { + continue; + } + // read the directory + if (dir.getFilenames() == null) { + dir.readDir(); + } + String[] dirFiles = dir.getFilenames(); + // try the same filename as the original + int fileIdx = Arrays.binarySearch(dirFiles, fn); + if (fileIdx < 0) { + // try closest matches without extension + fileIdx = -fileIdx - 1; + // try idx + if ((fileIdx < dirFiles.length) + && (FileOps.basename(dirFiles[fileIdx]).equals(baseFn))) { + // idx ok + } else if ((fileIdx > 0) + && (FileOps.basename(dirFiles[fileIdx - 1]) + .equals(baseFn))) { + // idx-1 ok + fileIdx = fileIdx - 1; + } else if ((fileIdx+1 < dirFiles.length) + && (FileOps.basename(dirFiles[fileIdx + 1]) + .equals(baseFn))) { + // idx+1 ok + fileIdx = fileIdx + 1; + } else { + // basename doesn't match + continue; + } + } + if (FileOps.classForFilename(dirFiles[fileIdx]) == fileClass) { + /* logger.debug("adding file " + dirFiles[fileIdx] + + " to Fileset " + this.getName()); */ + add(new ImageFile(dirFiles[fileIdx], this, dir)); + } + } + } + + /** + * Checks metadata and sets resolution in resX and resY. + * + */ + public void checkMeta() { + if (metaChecked) { + return; + } + if (fileMeta == null) { + // try to read metadata file + readMeta(); + if (fileMeta == null) { + // try directory metadata + ((DocuDirectory) parentDir).checkMeta(); + if (((DocuDirectory) parentDir).getDirMeta() != null) { + fileMeta = ((DocuDirectory) parentDir).getDirMeta(); + } else { + // try parent directory metadata + DocuDirectory gp = (DocuDirectory) parentDir.getParent(); + if (gp != null) { + gp.checkMeta(); + if (gp.getDirMeta() != null) { + fileMeta = gp.getDirMeta(); + } + } + } + } + } + if (fileMeta == null) { + // no metadata available + metaChecked = true; + return; + } + metaChecked = true; + float dpi = 0; + float dpix = 0; + float dpiy = 0; + float sizex = 0; + float sizey = 0; + float pixx = 0; + float pixy = 0; + // DPI is valid for X and Y + if (fileMeta.containsKey("original-dpi")) { + try { + dpi = Float.parseFloat((String) fileMeta.get("original-dpi")); + } catch (NumberFormatException e) { + } + if (dpi != 0) { + resX = dpi; + resY = dpi; + return; + } + } + // DPI-X and DPI-Y + if (fileMeta.containsKey("original-dpi-x") + && fileMeta.containsKey("original-dpi-y")) { + try { + dpix = Float.parseFloat((String) fileMeta + .get("original-dpi-x")); + dpiy = Float.parseFloat((String) fileMeta + .get("original-dpi-y")); + } catch (NumberFormatException e) { + } + if ((dpix != 0) && (dpiy != 0)) { + resX = dpix; + resY = dpiy; + return; + } + } + // SIZE-X and SIZE-Y and PIXEL-X and PIXEL-Y + if (fileMeta.containsKey("original-size-x") + && fileMeta.containsKey("original-size-y") + && fileMeta.containsKey("original-pixel-x") + && fileMeta.containsKey("original-pixel-y")) { + try { + sizex = Float.parseFloat((String) fileMeta + .get("original-size-x")); + sizey = Float.parseFloat((String) fileMeta + .get("original-size-y")); + pixx = Float.parseFloat((String) fileMeta + .get("original-pixel-x")); + pixy = Float.parseFloat((String) fileMeta + .get("original-pixel-y")); + } catch (NumberFormatException e) { + } + if ((sizex != 0) && (sizey != 0) && (pixx != 0) && (pixy != 0)) { + resX = pixx / (sizex * 100 / 2.54f); + resY = pixy / (sizey * 100 / 2.54f); + return; + } + } + } + + /* (non-Javadoc) + * @see digilib.io.DocuDirent#readMeta() + */ + public void readMeta() { + if ((fileMeta != null) || (file == null)) { + // there is already metadata or there is no file + return; + } + // metadata is in the file {filename}.meta + String fn = file.getAbsolutePath(); + File mf = new File(fn + ".meta"); + if (mf.canRead()) { + XMLMetaLoader ml = new XMLMetaLoader(); + try { + // read meta file + Map meta = ml.loadURL(mf.getAbsolutePath()); + if (meta == null) { + return; + } + fileMeta = meta.get(name); + } catch (Exception e) { + Logger.getLogger(this.getClass()).warn("error reading file .meta", e); + } + } + } + + +} diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/ImageFileset.java --- a/servlet/src/digilib/io/ImageFileset.java Fri Jan 07 17:47:24 2011 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,414 +0,0 @@ -/* ImageFileset -- digilib image file info class. - * 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.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; - -import digilib.image.ImageSize; -import digilib.io.FileOps.FileClass; -import digilib.servlet.DigilibConfiguration; - -/** - * @author casties - */ -public class ImageFileset extends DocuDirent { - - /** this is an image file */ - protected static FileClass fileClass = FileClass.IMAGE; - - /** list of files (ImageFile) */ - private List list = null; - - /** aspect ratio (width/height) */ - private float aspect = 0; - - /** resolution of the biggest image (DPI) */ - private float resX = 0; - - /** resolution of the biggest image (DPI) */ - private float resY = 0; - - /** - * Creator for empty fileset. - * - * - * @param initialCapacity - */ - public ImageFileset() { - list = new ArrayList(); - } - - /** - * Constructor with a file and hints. - * - * The hints are expected to contain 'basedirs' and 'scaledfilext' keys. - * - * @param file - * @param hints - */ - public ImageFileset(File file, Map hints) { - Directory[] dirs = (Directory[]) hints.get(FileOps.HINT_BASEDIRS); - int nb = dirs.length; - list = new ArrayList(nb); - parent = dirs[0]; - fill(dirs, file, hints); - } - - /** - * Adds an ImageFile to this Fileset. - * - * The files should be added in the order of higher to lower resolutions. - * The first file is considered the hires "original". - * - * - * @param f - * file to add - * @return true (always) - */ - public boolean add(ImageFile f) { - f.setParent(this); - return list.add(f); - } - - /** - * The number of image files in this Fileset. - * - * - * @return number of image files - */ - public int size() { - return (list != null) ? list.size() : 0; - } - - /** - * Gets the default File. - * - */ - public File getFile() { - return (list != null) ? list.get(0).getFile() : null; - } - - /** - * Get the ImageFile at the index. - * - * - * @param index - * @return - */ - public ImageFile get(int index) { - return list.get(index); - } - - /** - * Get the next smaller ImageFile than the given size. - * - * Returns the ImageFile from the set that has a width and height smaller or - * equal the given size. Returns null if there isn't any smaller image. - * Needs DocuInfo instance to checkFile(). - * - * - * @param size - * @param info - * @return - */ - public ImageFile getNextSmaller(ImageSize size) { - for (Iterator i = getHiresIterator(); i.hasNext();) { - ImageFile f = i.next(); - try { - if (!f.isChecked()) { - DigilibConfiguration.docuImageIdentify(f); - } - if (f.getSize().isTotallySmallerThan(size)) { - return f; - } - } catch (IOException e) { - } - } - return null; - } - - /** - * Get the next bigger ImageFile than the given size. - * - * Returns the ImageFile from the set that has a width or height bigger or - * equal the given size. Returns null if there isn't any bigger image. Needs - * DocuInfo instance to checkFile(). - * - * - * @param size - * @param info - * @return - */ - public ImageFile getNextBigger(ImageSize size) { - for (ListIterator i = getLoresIterator(); i.hasPrevious();) { - ImageFile f = i.previous(); - try { - if (!f.isChecked()) { - DigilibConfiguration.docuImageIdentify(f); - } - if (f.getSize().isBiggerThan(size)) { - return f; - } - } catch (IOException e) { - } - } - return null; - } - - /** - * Returns the biggest ImageFile in the set. - * - * - * @return - */ - public ImageFile getBiggest() { - return this.get(0); - } - - /** - * Returns the biggest ImageFile in the set. - * - * - * @return - */ - public ImageFile getSmallest() { - return this.get(this.size() - 1); - } - - /** - * Get an Iterator for this Fileset starting at the highest resolution - * images. - * - * - * @return - */ - public ListIterator getHiresIterator() { - return list.listIterator(); - } - - /** - * Get an Iterator for this Fileset starting at the lowest resolution - * images. - * - * The Iterator starts at the last element, so you have to use it backwards - * with hasPrevious() and previous(). - * - * - * @return - */ - public ListIterator getLoresIterator() { - return list.listIterator(list.size()); - } - - /** - * Fill the ImageFileset with files from different base directories. - * - * - * @param dirs - * list of base directories - * @param fl - * file (from first base dir) - * @param hints - * - */ - void fill(Directory[] dirs, File fl, Map hints) { - int nb = dirs.length; - String fn = fl.getName(); - String baseFn = FileOps.basename(fn); - // add the first ImageFile to the ImageFileset - add(new ImageFile(fn, this, parent)); - // iterate the remaining base directories - for (int dirIdx = 1; dirIdx < nb; dirIdx++) { - if (dirs[dirIdx] == null) { - continue; - } - // read the directory - if (dirs[dirIdx].getFilenames() == null) { - dirs[dirIdx].readDir(); - } - String[] dirFiles = dirs[dirIdx].getFilenames(); - // try the same filename as the original - int fileIdx = Arrays.binarySearch(dirFiles, fn); - if (fileIdx < 0) { - // try closest matches without extension - fileIdx = -fileIdx - 1; - // try idx - if ((fileIdx < dirFiles.length) - && (FileOps.basename(dirFiles[fileIdx]).equals(baseFn))) { - // idx ok - } else if ((fileIdx > 0) - && (FileOps.basename(dirFiles[fileIdx - 1]) - .equals(baseFn))) { - // idx-1 ok - fileIdx = fileIdx - 1; - } else if ((fileIdx+1 < dirFiles.length) - && (FileOps.basename(dirFiles[fileIdx + 1]) - .equals(baseFn))) { - // idx+1 ok - fileIdx = fileIdx + 1; - } else { - // basename doesn't match - continue; - } - } - if (FileOps.classForFilename(dirFiles[fileIdx]) == fileClass) { - /* logger.debug("adding file " + dirFiles[fileIdx] - + " to Fileset " + this.getName()); */ - add(new ImageFile(dirFiles[fileIdx], this, dirs[dirIdx])); - } - } - } - - /** - * Checks metadata and sets resolution in resX and resY. - * - */ - public void checkMeta() { - if (metaChecked) { - return; - } - if (fileMeta == null) { - // try to read metadata file - readMeta(); - if (fileMeta == null) { - // try directory metadata - ((DocuDirectory) parent).checkMeta(); - if (((DocuDirectory) parent).getDirMeta() != null) { - fileMeta = ((DocuDirectory) parent).getDirMeta(); - } else { - // try parent directory metadata - DocuDirectory gp = (DocuDirectory) parent.getParent(); - if (gp != null) { - gp.checkMeta(); - if (gp.getDirMeta() != null) { - fileMeta = gp.getDirMeta(); - } - } - } - } - } - if (fileMeta == null) { - // no metadata available - metaChecked = true; - return; - } - metaChecked = true; - float dpi = 0; - float dpix = 0; - float dpiy = 0; - float sizex = 0; - float sizey = 0; - float pixx = 0; - float pixy = 0; - // DPI is valid for X and Y - if (fileMeta.containsKey("original-dpi")) { - try { - dpi = Float.parseFloat((String) fileMeta.get("original-dpi")); - } catch (NumberFormatException e) { - } - if (dpi != 0) { - resX = dpi; - resY = dpi; - return; - } - } - // DPI-X and DPI-Y - if (fileMeta.containsKey("original-dpi-x") - && fileMeta.containsKey("original-dpi-y")) { - try { - dpix = Float.parseFloat((String) fileMeta - .get("original-dpi-x")); - dpiy = Float.parseFloat((String) fileMeta - .get("original-dpi-y")); - } catch (NumberFormatException e) { - } - if ((dpix != 0) && (dpiy != 0)) { - resX = dpix; - resY = dpiy; - return; - } - } - // SIZE-X and SIZE-Y and PIXEL-X and PIXEL-Y - if (fileMeta.containsKey("original-size-x") - && fileMeta.containsKey("original-size-y") - && fileMeta.containsKey("original-pixel-x") - && fileMeta.containsKey("original-pixel-y")) { - try { - sizex = Float.parseFloat((String) fileMeta - .get("original-size-x")); - sizey = Float.parseFloat((String) fileMeta - .get("original-size-y")); - pixx = Float.parseFloat((String) fileMeta - .get("original-pixel-x")); - pixy = Float.parseFloat((String) fileMeta - .get("original-pixel-y")); - } catch (NumberFormatException e) { - } - if ((sizex != 0) && (sizey != 0) && (pixx != 0) && (pixy != 0)) { - resX = pixx / (sizex * 100 / 2.54f); - resY = pixy / (sizey * 100 / 2.54f); - return; - } - } - } - - /** - * @return - */ - public float getResX() { - return resX; - } - - /** - * @return - */ - public float getResY() { - return resY; - } - - /** - * Sets the aspect ratio from an ImageSize. - * - * - * @param f - */ - public void setAspect(ImageSize s) { - aspect = s.getAspect(); - } - - /** - * Returns the aspect ratio. - * - * Aspect ratio is (width/height). So it's <1 for portrait and >1 for - * landscape. - * - * - * @return - */ - public float getAspect() { - return aspect; - } - -} \ No newline at end of file diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/ImageInput.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/ImageInput.java Sun Jan 09 21:11:03 2011 +0100 @@ -0,0 +1,151 @@ +/* ImageInput-- digilib image input interface. + + Digital Image Library servlet components + + Copyright (C) 2010 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 20.12.2010 + */ + +package digilib.io; + +import java.io.File; +import java.io.InputStream; + +import javax.imageio.stream.ImageInputStream; + +import digilib.image.ImageSize; + +public abstract class ImageInput { + + // mime file type + protected String mimetype = null; + // image size in pixels + protected ImageSize pixelSize = null; + protected ImageSet parent = null; + + /** + * @return ImageSize + */ + public ImageSize getSize() { + return pixelSize; + } + + /** + * Sets the imageSize. + * @param imageSize The imageSize to set + */ + public void setSize(ImageSize imageSize) { + this.pixelSize = imageSize; + } + + /** + * @return String + */ + public String getMimetype() { + return mimetype; + } + + /** + * Sets the mimetype. + * @param mimetype The mimetype to set + */ + public void setMimetype(String filetype) { + this.mimetype = filetype; + } + + /** returns if this image has been checked + * (i.e. has size and mimetype) + * TODO: deprecated + * @return boolean + */ + public boolean isChecked() { + return (pixelSize != null); + } + + /** Returns the aspect ratio of the image (width/height). + * + * @return + */ + public float getAspect() { + return (pixelSize != null) ? pixelSize.getAspect() : 0f; + } + + /** + * @return ImageSet + */ + public ImageSet getParent() { + return parent; + } + + /** + * Sets the parent. + * @param parent The parent to set + */ + public void setParent(ImageSet parent) { + this.parent = parent; + } + + /** Returns if the input can be returned as ImageInputStream. + * + * @return + */ + public boolean hasImageInputStream() { + return false; + } + + /** Returns the input as ImageInputStream (if available) + * + * @return + */ + public ImageInputStream getImageInputStream() { + return null; + } + + /** Returns if the input can be returned as InputStream. + * + * @return + */ + public boolean hasInputStream() { + return false; + } + + /** Returns the input as InputStream (if available) + * + * @return + */ + public InputStream getInputStream() { + return null; + } + + /** Returns if the input can be returned as File. + * + * @return + */ + public boolean hasFile() { + return false; + } + + /** Returns the input as File (if available) + * + * @return + */ + public File getFile() { + return null; + } + + + +} \ No newline at end of file diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/ImageSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/ImageSet.java Sun Jan 09 21:11:03 2011 +0100 @@ -0,0 +1,209 @@ +/* ImageSet -- digilib image file info class. + * 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.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import digilib.image.ImageSize; + +/** + * @author casties + */ +public class ImageSet { + + /** list of files (ImageFile) */ + protected List list = null; + + /** aspect ratio (width/height) */ + protected float aspect = 0f; + + /** resolution of the biggest image (DPI) */ + protected float resX = 0f; + + /** resolution of the biggest image (DPI) */ + protected float resY = 0f; + + /** + * Creator for empty fileset. + * + * + * @param initialCapacity + */ + public ImageSet() { + list = new ArrayList(); + } + + /** + * The number of image files in this Fileset. + * + * + * @return number of image files + */ + public int size() { + return (list != null) ? list.size() : 0; + } + + /** + * Gets the default Input. + * + */ + public ImageInput get() { + return (list != null) ? list.get(0) : null; + } + + /** + * Get the ImageFile at the index. + * + * + * @param index + * @return + */ + public ImageInput get(int index) { + return list.get(index); + } + + /** + * Get the next smaller ImageFile than the given size. + * + * Returns the ImageFile from the set that has a width and height smaller or + * equal the given size. Returns null if there isn't any smaller image. + * + * @param size + * @param info + * @return + */ + public ImageInput getNextSmaller(ImageSize size) { + for (ListIterator i = getHiresIterator(); i.hasNext();) { + ImageInput f = i.next(); + if (f.getSize().isTotallySmallerThan(size)) { + return f; + } + } + return null; + } + + /** + * Get the next bigger ImageFile than the given size. + * + * Returns the ImageFile from the set that has a width or height bigger or + * equal the given size. Returns null if there isn't any bigger image. + * + * @param size + * @param info + * @return + */ + public ImageInput getNextBigger(ImageSize size) { + for (ListIterator i = getLoresIterator(); i.hasPrevious();) { + ImageInput f = i.previous(); + if (f.getSize().isBiggerThan(size)) { + return f; + } + } + return null; + } + + /** + * Returns the biggest ImageFile in the set. + * + * + * @return + */ + public ImageInput getBiggest() { + return this.get(0); + } + + /** + * Returns the biggest ImageFile in the set. + * + * + * @return + */ + public ImageInput getSmallest() { + return this.get(this.size() - 1); + } + + /** + * Get an Iterator for this Fileset starting at the highest resolution + * images. + * + * + * @return + */ + public ListIterator getHiresIterator() { + return list.listIterator(); + } + + /** + * Get an Iterator for this Fileset starting at the lowest resolution + * images. + * + * The Iterator starts at the last element, so you have to use it backwards + * with hasPrevious() and previous(). + * + * + * @return + */ + public ListIterator getLoresIterator() { + return list.listIterator(list.size()); + } + + /** + * @return + */ + public float getResX() { + return resX; + } + + /** + * @return + */ + public float getResY() { + return resY; + } + + /** + * Sets the aspect ratio from an ImageSize. + * + * + * @param f + */ + public void setAspect(ImageSize s) { + aspect = s.getAspect(); + } + + /** + * Returns the aspect ratio. + * + * Aspect ratio is (width/height). So it's <1 for portrait and >1 for + * landscape. + * + * + * @return + */ + public float getAspect() { + return aspect; + } + + public void checkMeta() { + // TODO Auto-generated method stub + + } + +} \ No newline at end of file diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/ImageStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/ImageStream.java Sun Jan 09 21:11:03 2011 +0100 @@ -0,0 +1,41 @@ +/** + * + */ +package digilib.io; + +import java.io.InputStream; + +/** + * @author casties + * + */ +public class ImageStream extends ImageInput { + + 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 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/MetadataMap.java --- a/servlet/src/digilib/io/MetadataMap.java Fri Jan 07 17:47:24 2011 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -/** - * - */ -package digilib.io; - -import java.util.HashMap; - -/** Map for metadata related to files. - * @author casties - * - */ -public class MetadataMap extends HashMap { - -} diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/SVGFile.java --- a/servlet/src/digilib/io/SVGFile.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/io/SVGFile.java Sun Jan 09 21:11:03 2011 +0100 @@ -30,7 +30,7 @@ * @author casties * */ -public class SVGFile extends DocuDirent { +public class SVGFile extends DocuDirentImpl { /** this is a text file */ protected static FileClass fileClass = FileClass.SVG; /** our File instance */ diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/TextFile.java --- a/servlet/src/digilib/io/TextFile.java Fri Jan 07 17:47:24 2011 +0100 +++ b/servlet/src/digilib/io/TextFile.java Sun Jan 09 21:11:03 2011 +0100 @@ -30,7 +30,7 @@ * @author casties * */ -public class TextFile extends DocuDirent { +public class TextFile extends DocuDirentImpl { /** this is a text file */ protected static FileClass fileClass = FileClass.TEXT; /** our File instance */ diff -r 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/XMLListLoader.java --- a/servlet/src/digilib/io/XMLListLoader.java Fri Jan 07 17:47:24 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 85e465e6a642 -r e8668edcb880 servlet/src/digilib/io/XMLMetaLoader.java --- a/servlet/src/digilib/io/XMLMetaLoader.java Fri Jan 07 17:47:24 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 85e465e6a642 -r e8668edcb880 servlet/src/digilib/meta/MetadataMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/meta/MetadataMap.java Sun Jan 09 21:11:03 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 85e465e6a642 -r e8668edcb880 servlet/src/digilib/meta/XMLMetaLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/meta/XMLMetaLoader.java Sun Jan 09 21:11:03 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 85e465e6a642 -r e8668edcb880 servlet/src/digilib/pdf/DigilibInfoReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/pdf/DigilibInfoReader.java Sun Jan 09 21:11:03 2011 +0100 @@ -0,0 +1,76 @@ +package digilib.pdf; + +/** DigilibInfoReader + * A class for reading the information from info.xml files used in digilib image directories. + * + */ + +import java.io.File; +import java.util.List; + +import org.apache.log4j.Logger; +import org.jdom.Document; +import org.jdom.Element; +import org.jdom.input.SAXBuilder; + + + +public class DigilibInfoReader { + + /** gengeral logger for this class */ + protected static Logger logger = Logger.getLogger("digilib.servlet"); + + private String filename = null; + //private static String base_element = "info"; + + public DigilibInfoReader(String fn){ + filename = fn; + } + + /** + * Returns the attribute defined by 'attr' as a String. + * + * @param attr + * @return + */ + @SuppressWarnings("unchecked") // Element.getChildren() returns naked List + public String getAsString(String attr){ + try{ + SAXBuilder builder = new SAXBuilder(); + Document doc = builder.build(new File(filename)); + Element root = doc.getRootElement(); + List mainElements = root.getChildren(); + // logger.debug("XML mainElements:"+mainElements.toString()); + + for(int i=0; i 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 85e465e6a642 -r e8668edcb880 servlet/src/digilib/util/XMLListLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/util/XMLListLoader.java Sun Jan 09 21:11:03 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(); + } + +}