view servlet2/src/main/java/digilib/servlet/ScalerNoThread.java @ 1019:287e2d2d2ae8

fix flicker in Firefox by leaving scaler background visible. add setSize and setRGB actions. disabled rotation slider for now (needs excact numerical input option).
author robcast
date Mon, 20 Feb 2012 22:23:07 +0100
parents 7779b37d1d05
children
line wrap: on
line source

package digilib.servlet;

import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import digilib.auth.AuthOpException;
import digilib.auth.AuthOps;
import digilib.image.DocuImage;
import digilib.image.ImageJobDescription;
import digilib.image.ImageOpException;
import digilib.image.ImageWorker;
import digilib.io.DocuDirCache;
import digilib.io.DocuDirectory;
import digilib.io.ImageInput;

/**
 * Version of Scaler servlet that doesn't use a thread pool.
 */
public class ScalerNoThread extends HttpServlet {

    private static final long serialVersionUID = 1450947819851623306L;

    /** digilib servlet version (for all components) */
    public static final String version = "1.9.0a5 nothread";

    /** servlet error codes */
    public static enum Error {UNKNOWN, AUTH, FILE, IMAGE};
    
    /** type of error message */
    public static enum ErrMsg {IMAGE, TEXT, CODE};
    
    /** logger for accounting requests */
    protected static Logger accountlog = Logger.getLogger("account.request");

    /** gengeral logger for this class */
    protected static Logger logger = Logger.getLogger("digilib.scaler");

    /** logger for authentication related */
    protected static Logger authlog = Logger.getLogger("digilib.auth");

    /** DocuDirCache instance */
    protected DocuDirCache dirCache;

    /** authentication error image file */
    public static File denyImgFile;

    /** image error image file */
    public static File errorImgFile;

    /** not found error image file */
    public static File notfoundImgFile;

    /** send files as is? */
    protected boolean sendFileAllowed = true;

    /** DigilibConfiguration instance */
    protected DigilibServletConfiguration dlConfig;

    /** use authorization database */
    protected boolean useAuthorization = true;

    /** AuthOps instance */
    protected AuthOps authOp;

    /**
     * Initialisation on first run.
     * 
     * @throws ServletException
     * 
     * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
     */
    public void init(ServletConfig config) throws ServletException {
        super.init(config);

        System.out
                .println("***** Digital Image Library Image Scaler Servlet (version "
                        + version + ") *****");
        // say hello in the log file
        logger.info("***** Digital Image Library Image Scaler Servlet (version "
                + version + ") *****");

        // get our ServletContext
        ServletContext context = config.getServletContext();
        // see if there is a Configuration instance
        dlConfig = (DigilibServletConfiguration) context
                .getAttribute("digilib.servlet.configuration");
        if (dlConfig == null) {
            // no Configuration
            throw new ServletException("No Configuration!");
        }
        // set our AuthOps
        useAuthorization = dlConfig.getAsBoolean("use-authorization");
        authOp = (AuthOps) dlConfig.getValue("servlet.auth.op");

        // DocuDirCache instance
        dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");

        denyImgFile = ServletOps.getFile(
                (File) dlConfig.getValue("denied-image"), context);
        errorImgFile = ServletOps.getFile(
                (File) dlConfig.getValue("error-image"), context);
        notfoundImgFile = ServletOps.getFile(
                (File) dlConfig.getValue("notfound-image"), context);
        sendFileAllowed = dlConfig.getAsBoolean("sendfile-allowed");
    }

    /** Returns modification time relevant to the request for caching.
     * 
     * @see javax.servlet.http.HttpServlet#getLastModified(javax.servlet.http.HttpServletRequest)
     */
    public long getLastModified(HttpServletRequest request) {
        accountlog.debug("GetLastModified from " + request.getRemoteAddr()
                + " for " + request.getQueryString());
        long mtime = -1;
        // create new request
        DigilibServletRequest dlReq = new DigilibServletRequest(request);
        DocuDirectory dd = dirCache.getDirectory(dlReq.getFilePath());
        if (dd != null) {
            mtime = dd.getDirMTime() / 1000 * 1000;
        }
        logger.debug("  returns "+mtime);
        return mtime;
    }

    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
        accountlog.info("GET from " + request.getRemoteAddr());
        this.processRequest(request, response);
    }


    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException {
        accountlog.info("POST from " + request.getRemoteAddr());
        this.processRequest(request, response);
    }
    

	protected void doHead(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		logger.debug("HEAD from "+req.getRemoteAddr());
		super.doHead(req, resp);
	}

	protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		logger.debug("OPTIONS from "+req.getRemoteAddr());
		super.doOptions(req, resp);
	}

	/** Service this request using the response.
     * @param request
     * @param response
     * @throws ServletException 
     */
    public void processRequest(HttpServletRequest request,
            HttpServletResponse response) throws ServletException {

        if (dlConfig == null) {
            logger.error("ERROR: No Configuration!");
            throw new ServletException("NO VALID digilib CONFIGURATION!");
        }

        accountlog.debug("request: " + request.getQueryString());
        logger.debug("request: " + request.getQueryString());
        long startTime = System.currentTimeMillis();

        // parse request
        DigilibServletRequest dlRequest = new DigilibServletRequest(request);
        // extract the job information
        ImageJobDescription jobTicket = ImageJobDescription.getInstance(dlRequest, dlConfig);

        // type of error reporting
        ErrMsg errMsgType = ErrMsg.IMAGE;
        if (dlRequest.hasOption("errtxt")) {
        	errMsgType = ErrMsg.TEXT;
        } else if (dlRequest.hasOption("errcode")) {
        	errMsgType = ErrMsg.CODE;
        }
        
        try {
        	/*
        	 *  check if we can fast-track without scaling
        	 */
            ImageInput fileToLoad = (ImageInput) jobTicket.getInput();

            // check permissions
            if (useAuthorization) {
                // get a list of required roles (empty if no restrictions)
                List<String> rolesRequired = authOp.rolesForPath(
                        jobTicket.getFilePath(), request);
                if (rolesRequired != null) {
                    authlog.debug("Role required: " + rolesRequired);
                    authlog.debug("User: " + request.getRemoteUser());
                    // is the current request/user authorized?
                    if (!authOp.isRoleAuthorized(rolesRequired, request)) {
                        // send deny answer and abort
                        throw new AuthOpException();
                    }
                }
            }

            // if requested, send image as a file
            if (sendFileAllowed && jobTicket.getSendAsFile()) {
                String mt = null;
                if (jobTicket.hasOption("rawfile")) {
                    mt = "application/octet-stream";
                }
                logger.debug("Sending RAW File as is.");
                ServletOps.sendFile(fileToLoad.getFile(), mt, null, response, logger);
                logger.info("Done in " + (System.currentTimeMillis() - startTime) + "ms");
                return;
            }

            // if possible, send the image without actually having to transform it
            if (! jobTicket.isTransformRequired()) {
                logger.debug("Sending File as is.");
                ServletOps.sendFile(fileToLoad.getFile(), null, null, response, logger);
                logger.info("Done in " + (System.currentTimeMillis() - startTime) + "ms");
                return;
            }

            // create job
            ImageWorker job = new ImageWorker(dlConfig, jobTicket);
            // get result immediately
            DocuImage img = job.call();
            // forced destination image type
            String mt = null;
            if (jobTicket.hasOption("jpg")) {
            	mt = "image/jpeg";
            } else if (jobTicket.hasOption("png")) {
            	mt = "image/png";
            }
            // send image
            ServletOps.sendImage(img, mt, response, logger);
            logger.debug("Job Processing Time: "
                    + (System.currentTimeMillis() - startTime) + "ms");

        } catch (ImageOpException e) {
            logger.error(e.getClass() + ": " + e.getMessage());
            digilibError(errMsgType, Error.IMAGE, null, response);
        } catch (IOException e) {
            logger.error(e.getClass() + ": " + e.getMessage());
            digilibError(errMsgType, Error.FILE, null, response);
        } catch (AuthOpException e) {
            logger.error(e.getClass() + ": " + e.getMessage());
            digilibError(errMsgType, Error.AUTH, null, response);
        }

    }

    /**
     * Sends an error to the client as text or image.
     * 
     * @param type
     * @param error
     * @param msg
     * @param response
     */
    public static void digilibError(ErrMsg type, Error error, String msg,
            HttpServletResponse response) {
        try {
            File img = null;
            int status = 0;
            if (error == Error.AUTH) {
                if (msg == null) {
                    msg = "ERROR: Unauthorized access!";
                }
                img = denyImgFile;
                status = HttpServletResponse.SC_FORBIDDEN;
            } else if (error == Error.FILE) {
                if (msg == null) {
                    msg = "ERROR: Image file not found!";
                }
                img = notfoundImgFile;
                status = HttpServletResponse.SC_NOT_FOUND;
            } else {
                if (msg == null) {
                    msg = "ERROR: Other image error!";
                }
                img = errorImgFile;
                status = HttpServletResponse.SC_BAD_REQUEST;
            }
            if (response.isCommitted()) {
                // response already committed
                logger.error("Unable to send error: " + msg);
                return;
            }
            if (type == ErrMsg.TEXT) {
                ServletOps.htmlMessage(msg, response);
            } else if (type == ErrMsg.CODE) {
                response.sendError(status, msg);
            } else if (img != null) {
                // default: image
                ServletOps.sendFile(img, null, null, response, logger);
            }
        } catch (Exception e) {
            logger.error("Error sending error!", e);
        }

    }

    public static String getVersion() {
        return version;
    }

}