Java tutorial
/* * 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; } }