net.sf.ginp.GinpPictureServlet.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.ginp.GinpPictureServlet.java

Source

/*
 *  ginp - Java Web Application for Viewing Photo Collections
 *  Copyright (C) 2004  Douglas John Culnane <doug@culnane.net>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA  02110-1301  USA
 */
package net.sf.ginp;

import net.sf.ginp.config.ModelUtil;
import net.sf.ginp.util.GinpUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *  Servlet that delivers Images to the client's browser.
 *
 *@author     Doug Culnane
 *@author     Justin Sher
 *@version    $Revision$
 */
public class GinpPictureServlet extends HttpServlet {
    /**
     *
     */
    private static final long serialVersionUID = 1937043430753224685L;

    /**
     *  apache Commons Logger specific to this class.
     */
    private Log log = LogFactory.getLog(GinpPictureServlet.class);

    /**
     *  Called by HTTP GET.
     *
     *@param  req                   HTTP GET Request
     *@param  res                   HTTP Response
     *@exception  IOException       Description of the Exception
     */
    public final void doGet(final HttpServletRequest req, final HttpServletResponse res) throws IOException {
        doHttpMethod(req, res);
    }

    /**
     *  Called by HTTP POST.
     *
     *@param  req                   HTTP POST Request
     *@param  res                   HTTP Response
     *@exception  IOException       Description of the Exception
     */
    public final void doPost(final HttpServletRequest req, final HttpServletResponse res) throws IOException {
        doHttpMethod(req, res);
    }

    /**
     *  Central Processor of HTTP GET and POST Methods. This method gets the
     *  model for the users session, and returns the correctly sized picture
     *  based on the command parameters in the request and the model state.
     *
     *@param  req                   HTTP Request
     *@param  res                   HTTP Response
     *@exception  IOException       Description of the Exception
     */
    final void doHttpMethod(final HttpServletRequest req, final HttpServletResponse res) throws IOException {
        ServletOutputStream sos = res.getOutputStream();
        GinpModel model = null;

        //Retrieve the model for this web app
        try {
            model = ModelUtil.getModel(req);
        } catch (Exception ex) {
            log.error("Problem getting model", ex);

            return;
        }

        String filename = req.getParameter("name");
        String path = req.getParameter("path");

        res.setContentType("image/jpeg");

        //Only allow files below the given directory
        if (filename != null) {
            filename = filename.replaceAll("\\.\\./", "");
            filename = filename.replaceAll("\\.\\.\\\\", "");

            // Only deliver JPEGs
            if (!((filename.toLowerCase()).endsWith(".jpg") || (filename.toLowerCase()).endsWith(".jpeg"))) {
                filename = null;
            }
        }

        if (path != null) {
            path = path.replaceAll("\\.\\./", "");
            path = path.replaceAll("\\.\\.\\\\", "");
        }

        if (filename != null) {
            String absPath = getImagePath(model, path);

            int maxSize = 0;
            File fl;

            if (req.getParameter("maxsize") != null) {
                maxSize = GinpUtil.parseInteger(req, "maxsize", 0);
                fl = getThumbnailPath(filename, absPath, maxSize);
            } else {
                fl = new File(absPath + filename);
            }

            fl = handleMissingPicture(req, res, fl);

            FileInputStream is = new FileInputStream(fl);

            String heightParm = req.getParameter("height");
            String widthParm = req.getParameter("width");

            // debug output
            //if (log.isDebugEnabled()) {
            log.info("doHttpMethod filename=" + filename + " absPath=" + absPath + " path=" + path + " heightParm="
                    + heightParm + " widthParm=" + widthParm + " maxSize=" + maxSize + " ImageFile="
                    + fl.getPath());

            //}
            if ((heightParm != null) || (widthParm != null)) {
                int width = GinpUtil.parseInteger(req, "width", 0);
                int height = GinpUtil.parseInteger(req, "height", 0);
                GinpUtil.writeScaledImageToStream(sos, is, width, height);
            } else {
                // deliver raw image
                GinpUtil.writeInputStreamToOutputStream(sos, is);
            }
        } else {
            // is this a request to set client info
            if ((req.getParameter("cmd") != null) && req.getParameter("cmd").equals("setprops")) {
                if (req.getParameter("pagewidth") != null) {
                    int i = GinpUtil.parseInteger(req, "pagewidth", 0);

                    if (i > 0) {
                        model.setPageWidth(i);
                    }
                }

                if (req.getParameter("pageheight") != null) {
                    int i = GinpUtil.parseInteger(req, "pageheight", 0);

                    if (i > 0) {
                        model.setPageHeight(i);
                    }
                }
            }

            deliverSpacer(req, sos);
        }

        sos.flush();
        sos.close();
    }

    /**
     * Handle missing picture handles the case where the image being linked
     * to does not exist. It returns the image "/img/nofile.jpg" and sets
     * the image to not cache so that if the image does appear later the
     * image will reload.  If the image exists it returns the origional
     * image passed.
     * @param req servlet request
     * @param res servlet response
     * @param fl file
     * @return the file to use as the image source file
     */
    private File handleMissingPicture(final HttpServletRequest req, final HttpServletResponse res, File fl) {
        if (!(fl.exists())) {
            log.info("File not found: " + fl.getAbsolutePath());

            fl = new File(req.getSession().getServletContext().getRealPath("/img/nofile.jpg"));

            // DO NOT cache this picture.
            res.setHeader("Expires", "-1");
            res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
            res.addHeader("Cache-Control", "post-check=0, pre-check=0");
            res.setHeader("Pragma", "no-cac`he");
        }

        return fl;
    }

    /**
     * Get the thumbnail path.
     * @param filename the name of the file
     * @param absPath the path its located in
     * @param maxSize the size it should be
     * @return the file object for the path
     */
    private File getThumbnailPath(final String filename, final String absPath, final int maxSize) {
        File fl;

        if (filename.indexOf("/") != -1) {
            fl = new File(absPath + filename.substring(0, filename.lastIndexOf("/")) + "/.ginp/" + maxSize + "-"
                    + filename.substring(filename.lastIndexOf("/") + 1));
        } else {
            fl = new File(absPath + ".ginp/" + maxSize + "-" + filename);
        }

        return fl;
    }

    /**
     * Send the Spacer gif to the client.
     * @param req servlet request
     * @param sos an output stream
     * @throws IOException subclass FileNotFoundException if we can't find
     * the spacer, or generic IOException if there is a problem delivering it
     */
    private void deliverSpacer(final HttpServletRequest req, final OutputStream sos) throws IOException {
        // deliver spacer.gif
        File fl = new File(req.getSession().getServletContext().getRealPath("/img/spacer.gif"));
        FileInputStream is = new FileInputStream(fl);
        GinpUtil.writeInputStreamToOutputStream(sos, is);
    }

    /**
     * Returns the disk path to the directory of pictures
     * that is currently being looked at.
     * @param model the Ginp Model
     * @param path the path that the user has selected.
     * @return the directory path
     */
    private String getImagePath(final GinpModel model, final String path) {
        if (path != null) {
            // check the path is the collections path
            if (!(model.getCollection().getPath().equals(path))) {
                // sync model with request
                model.getCollection().setPath(path);
            }
        }

        String absPath = model.getCollection().getRoot() + model.getCollection().getPath();

        return absPath;
    }
}