content: /* ===========================================================
   * JFreeChart : a free chart library for the Java(tm) platform
   * ===========================================================
   *
   * (C) Copyright 2000-2012, by Object Refinery Limited and Contributors.
   *
   * Project Info:  http://www.jfree.org/jfreechart/index.html
   *
   * 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
   * (at your option) 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.
   *
   * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   * Other names may be trademarks of their respective owners.]
   *
   * ---------------------
   * ServletUtilities.java
   * ---------------------
   * (C) Copyright 2002-2008, by Richard Atkinson and Contributors.
   *
   * Original Author:  Richard Atkinson;
   * Contributor(s):   J?rgen Hoffman;
   *                   David Gilbert (for Object Refinery Limited);
   *                   Douglas Clayton;
   *
   * Changes
   * -------
   * 19-Aug-2002 : Version 1;
   * 20-Apr-2003 : Added additional sendTempFile method to allow MIME type
   *               specification and modified original sendTempFile method to
   *               automatically set MIME type for JPEG and PNG files
   * 23-Jun-2003 : Added additional sendTempFile method at the request of
   *               J?rgen Hoffman;
   * 07-Jul-2003 : Added more header information to streamed images;
   * 19-Aug-2003 : Forced images to be stored in the temporary directory defined
   *               by System property java.io.tmpdir, rather than default (RA);
   * 24-Mar-2004 : Added temp filename prefix attribute (DG);
   * 09-Mar-2005 : Added "one time" file option (DG);
   * ------------- JFREECHART 1.0.x RELEASED ------------------------------------
   * 10-Jan-2006 : Updated API docs and reformatted (DG);
   * 13-Sep-2006 : Format date in response header in English, not locale default
   *               (see bug 1557141) (DG);
   *
   */
  
  package org.jfree.chart.servlet;
  
  import java.io.BufferedInputStream;
  import java.io.BufferedOutputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.text.SimpleDateFormat;
  import java.util.Date;
  import java.util.Locale;
  import java.util.TimeZone;
  
  import javax.servlet.http.HttpServletResponse;
  import javax.servlet.http.HttpSession;
  
  import org.jfree.chart.ChartRenderingInfo;
  import org.jfree.chart.ChartUtilities;
  import org.jfree.chart.JFreeChart;
  
  /**
   * Utility class used for servlet related JFreeChart operations.
   */
  public class ServletUtilities {
  
      /** The filename prefix. */
      private static String tempFilePrefix = "jfreechart-";
  
      /** A prefix for "one time" charts. */
      private static String tempOneTimeFilePrefix = "jfreechart-onetime-";
  
      /**
       * Returns the prefix for the temporary file names generated by this class.
       *
       * @return The prefix (never <code>null</code>).
       */
      public static String getTempFilePrefix() {
          return ServletUtilities.tempFilePrefix;
      }
  
      /**
       * Sets the prefix for the temporary file names generated by this class.
       *
       * @param prefix  the prefix (<code>null</code> not permitted).
       */
      public static void setTempFilePrefix(String prefix) {
          if (prefix == null) {
              throw new IllegalArgumentException("Null 'prefix' argument.");
          }
          ServletUtilities.tempFilePrefix = prefix;
      }
  
      /**
       * Returns the prefix for "one time" temporary file names generated by
       * this class.
       *
       * @return The prefix.
       */
      public static String getTempOneTimeFilePrefix() {
          return ServletUtilities.tempOneTimeFilePrefix;
      }
  
      /**
       * Sets the prefix for the "one time" temporary file names generated by
       * this class.
       *
       * @param prefix  the prefix (<code>null</code> not permitted).
       */
      public static void setTempOneTimeFilePrefix(String prefix) {
          if (prefix == null) {
              throw new IllegalArgumentException("Null 'prefix' argument.");
          }
          ServletUtilities.tempOneTimeFilePrefix = prefix;
      }
  
      /**
       * Saves the chart as a PNG format file in the temporary directory.
       *
       * @param chart  the JFreeChart to be saved.
       * @param width  the width of the chart.
       * @param height  the height of the chart.
       * @param session  the HttpSession of the client (if <code>null</code>, the
       *                 temporary file is marked as "one-time" and deleted by
       *                 the {@link DisplayChart} servlet right after it is
       *                 streamed to the client).
       *
       * @return The filename of the chart saved in the temporary directory.
       *
       * @throws IOException if there is a problem saving the file.
       */
      public static String saveChartAsPNG(JFreeChart chart, int width, int height,
              HttpSession session) throws IOException {
  
          return ServletUtilities.saveChartAsPNG(chart, width, height, null,
                  session);
  
      }
  
      /**
       * Saves the chart as a PNG format file in the temporary directory and
       * populates the {@link ChartRenderingInfo} object which can be used to
       * generate an HTML image map.
       *
       * @param chart  the chart to be saved (<code>null</code> not permitted).
       * @param width  the width of the chart.
       * @param height  the height of the chart.
       * @param info  the ChartRenderingInfo object to be populated
       *              (<code>null</code> permitted).
       * @param session  the HttpSession of the client (if <code>null</code>, the
       *                 temporary file is marked as "one-time" and deleted by
       *                 the {@link DisplayChart} servlet right after it is
       *                 streamed to the client).
       *
       * @return The filename of the chart saved in the temporary directory.
       *
       * @throws IOException if there is a problem saving the file.
       */
      public static String saveChartAsPNG(JFreeChart chart, int width, int height,
              ChartRenderingInfo info, HttpSession session) throws IOException {
  
          if (chart == null) {
              throw new IllegalArgumentException("Null 'chart' argument.");
          }
          ServletUtilities.createTempDir();
          String prefix = ServletUtilities.tempFilePrefix;
          if (session == null) {
              prefix = ServletUtilities.tempOneTimeFilePrefix;
          }
          File tempFile = File.createTempFile(prefix, ".png",
                  new File(System.getProperty("java.io.tmpdir")));
          ChartUtilities.saveChartAsPNG(tempFile, chart, width, height, info);
          if (session != null) {
              ServletUtilities.registerChartForDeletion(tempFile, session);
          }
          return tempFile.getName();
  
      }
  
      /**
       * Saves the chart as a JPEG format file in the temporary directory.
       * <p>
       * SPECIAL NOTE: Please avoid using JPEG as an image format for charts,
       * it is a "lossy" format that introduces visible distortions in the
       * resulting image - use PNG instead.  In addition, note that JPEG output
       * is supported by JFreeChart only for JRE 1.4.2 or later.
       *
       * @param chart  the JFreeChart to be saved.
       * @param width  the width of the chart.
       * @param height  the height of the chart.
       * @param session  the HttpSession of the client (if <code>null</code>, the
       *                 temporary file is marked as "one-time" and deleted by
       *                 the {@link DisplayChart} servlet right after it is
       *                 streamed to the client).
       *
       * @return The filename of the chart saved in the temporary directory.
       *
       * @throws IOException if there is a problem saving the file.
       */
      public static String saveChartAsJPEG(JFreeChart chart, int width,
                                           int height, HttpSession session)
              throws IOException {
  
          return ServletUtilities.saveChartAsJPEG(chart, width, height, null,
                  session);
  
      }
  
      /**
       * Saves the chart as a JPEG format file in the temporary directory and
       * populates the <code>ChartRenderingInfo</code> object which can be used
       * to generate an HTML image map.
       * <p>
       * SPECIAL NOTE: Please avoid using JPEG as an image format for charts,
       * it is a "lossy" format that introduces visible distortions in the
       * resulting image - use PNG instead.  In addition, note that JPEG output
       * is supported by JFreeChart only for JRE 1.4.2 or later.
       *
       * @param chart  the chart to be saved (<code>null</code> not permitted).
       * @param width  the width of the chart
       * @param height  the height of the chart
       * @param info  the ChartRenderingInfo object to be populated
       * @param session  the HttpSession of the client (if <code>null</code>, the
       *                 temporary file is marked as "one-time" and deleted by
       *                 the {@link DisplayChart} servlet right after it is
       *                 streamed to the client).
       *
       * @return The filename of the chart saved in the temporary directory
       *
       * @throws IOException if there is a problem saving the file.
       */
      public static String saveChartAsJPEG(JFreeChart chart, int width,
              int height, ChartRenderingInfo info, HttpSession session)
              throws IOException {
  
          if (chart == null) {
              throw new IllegalArgumentException("Null 'chart' argument.");
          }
  
          ServletUtilities.createTempDir();
          String prefix = ServletUtilities.tempFilePrefix;
          if (session == null) {
              prefix = ServletUtilities.tempOneTimeFilePrefix;
          }
          File tempFile = File.createTempFile(prefix, ".jpeg",
                  new File(System.getProperty("java.io.tmpdir")));
          ChartUtilities.saveChartAsJPEG(tempFile, chart, width, height, info);
          if (session != null) {
              ServletUtilities.registerChartForDeletion(tempFile, session);
          }
          return tempFile.getName();
  
      }
  
      /**
       * Creates the temporary directory if it does not exist.  Throws a
       * <code>RuntimeException</code> if the temporary directory is
       * <code>null</code>.  Uses the system property <code>java.io.tmpdir</code>
       * as the temporary directory.  This sounds like a strange thing to do but
       * my temporary directory was not created on my default Tomcat 4.0.3
       * installation.  Could save some questions on the forum if it is created
       * when not present.
       */
      protected static void createTempDir() {
          String tempDirName = System.getProperty("java.io.tmpdir");
          if (tempDirName == null) {
              throw new RuntimeException("Temporary directory system property "
                      + "(java.io.tmpdir) is null.");
          }
  
          // create the temporary directory if it doesn't exist
          File tempDir = new File(tempDirName);
          if (!tempDir.exists()) {
              tempDir.mkdirs();
          }
      }
  
      /**
       * Adds a {@link ChartDeleter} object to the session object with the name
       * <code>JFreeChart_Deleter</code> if there is not already one bound to the
       * session and adds the filename to the list of charts to be deleted.
       *
       * @param tempFile  the file to be deleted.
       * @param session  the HTTP session of the client.
       */
      protected static void registerChartForDeletion(File tempFile,
              HttpSession session) {
  
          //  Add chart to deletion list in session
          if (session != null) {
              ChartDeleter chartDeleter
                  = (ChartDeleter) session.getAttribute("JFreeChart_Deleter");
              if (chartDeleter == null) {
                  chartDeleter = new ChartDeleter();
                  session.setAttribute("JFreeChart_Deleter", chartDeleter);
              }
              chartDeleter.addChart(tempFile.getName());
          }
          else {
              System.out.println("Session is null - chart will not be deleted");
          }
      }
  
      /**
       * Binary streams the specified file in the temporary directory to the
       * HTTP response in 1KB chunks.
       *
       * @param filename  the name of the file in the temporary directory.
       * @param response  the HTTP response object.
       *
       * @throws IOException  if there is an I/O problem.
       */
      public static void sendTempFile(String filename,
              HttpServletResponse response) throws IOException {
  
          File file = new File(System.getProperty("java.io.tmpdir"), filename);
          ServletUtilities.sendTempFile(file, response);
      }
  
      /**
       * Binary streams the specified file to the HTTP response in 1KB chunks.
       *
       * @param file  the file to be streamed.
       * @param response  the HTTP response object.
       *
       * @throws IOException if there is an I/O problem.
       */
      public static void sendTempFile(File file, HttpServletResponse response)
              throws IOException {
  
          String mimeType = null;
          String filename = file.getName();
          if (filename.length() > 5) {
              if (filename.substring(filename.length() - 5,
                      filename.length()).equals(".jpeg")) {
                  mimeType = "image/jpeg";
              }
              else if (filename.substring(filename.length() - 4,
                      filename.length()).equals(".png")) {
                  mimeType = "image/png";
              }
          }
          ServletUtilities.sendTempFile(file, response, mimeType);
      }
  
      /**
       * Binary streams the specified file to the HTTP response in 1KB chunks.
       *
       * @param file  the file to be streamed.
       * @param response  the HTTP response object.
       * @param mimeType  the mime type of the file, null allowed.
       *
       * @throws IOException if there is an I/O problem.
       */
      public static void sendTempFile(File file, HttpServletResponse response,
                                      String mimeType) throws IOException {
  
          if (file.exists()) {
              BufferedInputStream bis = new BufferedInputStream(
                      new FileInputStream(file));
  
              //  Set HTTP headers
              if (mimeType != null) {
                  response.setHeader("Content-Type", mimeType);
              }
              response.setHeader("Content-Length", String.valueOf(file.length()));
              SimpleDateFormat sdf = new SimpleDateFormat(
                      "EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
              sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
              response.setHeader("Last-Modified",
                      sdf.format(new Date(file.lastModified())));
  
              BufferedOutputStream bos = new BufferedOutputStream(
                      response.getOutputStream());
              byte[] input = new byte[1024];
              boolean eof = false;
              while (!eof) {
                  int length = bis.read(input);
                  if (length == -1) {
                      eof = true;
                  }
                  else {
                      bos.write(input, 0, length);
                  }
              }
              bos.flush();
              bis.close();
              bos.close();
          }
          else {
              throw new FileNotFoundException(file.getAbsolutePath());
          }
      }
  
      /**
       * Perform a search/replace operation on a String
       * There are String methods to do this since (JDK 1.4)
       *
       * @param inputString  the String to have the search/replace operation.
       * @param searchString  the search String.
       * @param replaceString  the replace String.
       *
       * @return The String with the replacements made.
       */
      public static String searchReplace(String inputString,
                                         String searchString,
                                         String replaceString) {
  
          int i = inputString.indexOf(searchString);
          if (i == -1) {
              return inputString;
          }
  
          String r = "";
          r += inputString.substring(0, i) + replaceString;
          if (i + searchString.length() < inputString.length()) {
              r += searchReplace(inputString.substring(i + searchString.length()),
                      searchString, replaceString);
          }
  
          return r;
      }
  
  }
  