Source for org.jfree.chart.servlet.ServletUtilities

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
   6:  *
   7:  * Project Info:  http://www.jfree.org/jfreechart/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  *
  27:  * ---------------------
  28:  * ServletUtilities.java
  29:  * ---------------------
  30:  * (C) Copyright 2002-2006, by Richard Atkinson and Contributors.
  31:  *
  32:  * Original Author:  Richard Atkinson;
  33:  * Contributor(s):   J?rgen Hoffman;
  34:  *                   David Gilbert (for Object Refinery Limited);
  35:  *                   Douglas Clayton;
  36:  *
  37:  * $Id: ServletUtilities.java,v 1.3.2.2 2006/01/10 15:53:30 mungady Exp $
  38:  *
  39:  * Changes
  40:  * -------
  41:  * 19-Aug-2002 : Version 1;
  42:  * 20-Apr-2003 : Added additional sendTempFile method to allow MIME type 
  43:  *               specification and modified original sendTempFile method to 
  44:  *               automatically set MIME type for JPEG and PNG files
  45:  * 23-Jun-2003 : Added additional sendTempFile method at the request of 
  46:  *               J?rgen Hoffman;
  47:  * 07-Jul-2003 : Added more header information to streamed images;
  48:  * 19-Aug-2003 : Forced images to be stored in the temporary directory defined 
  49:  *               by System property java.io.tmpdir, rather than default (RA);
  50:  * 24-Mar-2004 : Added temp filename prefix attribute (DG);
  51:  * 09-Mar-2005 : Added "one time" file option (DG);
  52:  * ------------- JFREECHART 1.0.0 RELEASED ------------------------------------
  53:  * 10-Jan-2006 : Updated API docs and reformatted (DG);
  54:  *
  55:  */
  56: 
  57: package org.jfree.chart.servlet;
  58: 
  59: 
  60: import java.io.BufferedInputStream;
  61: import java.io.BufferedOutputStream;
  62: import java.io.File;
  63: import java.io.FileInputStream;
  64: import java.io.FileNotFoundException;
  65: import java.io.IOException;
  66: import java.text.SimpleDateFormat;
  67: import java.util.Date;
  68: import java.util.TimeZone;
  69: 
  70: import javax.servlet.http.HttpServletResponse;
  71: import javax.servlet.http.HttpSession;
  72: 
  73: import org.jfree.chart.ChartRenderingInfo;
  74: import org.jfree.chart.ChartUtilities;
  75: import org.jfree.chart.JFreeChart;
  76: 
  77: /**
  78:  * Utility class used for servlet related JFreeChart operations.
  79:  */
  80: public class ServletUtilities {
  81: 
  82:     /** The filename prefix. */
  83:     private static String tempFilePrefix = "jfreechart-";
  84:     
  85:     /** A prefix for "one time" charts. */
  86:     private static String tempOneTimeFilePrefix = "jfreechart-onetime-";
  87:     
  88:     /**
  89:      * Returns the prefix for the temporary file names generated by this class.
  90:      * 
  91:      * @return The prefix (never <code>null</code>).
  92:      */
  93:     public static String getTempFilePrefix() {
  94:         return ServletUtilities.tempFilePrefix;   
  95:     }
  96:     
  97:     /**
  98:      * Sets the prefix for the temporary file names generated by this class.
  99:      * 
 100:      * @param prefix  the prefix (<code>null</code> not permitted).
 101:      */
 102:     public static void setTempFilePrefix(String prefix) {
 103:         if (prefix == null) {
 104:             throw new IllegalArgumentException("Null 'prefix' argument.");   
 105:         }
 106:         ServletUtilities.tempFilePrefix = prefix;
 107:     }
 108:     
 109:     /**
 110:      * Returns the prefix for "one time" temporary file names generated by
 111:      * this class.
 112:      * 
 113:      * @return The prefix.
 114:      */
 115:     public static String getTempOneTimeFilePrefix() {
 116:         return ServletUtilities.tempOneTimeFilePrefix;
 117:     }
 118:     
 119:     /**
 120:      * Sets the prefix for the "one time" temporary file names generated by 
 121:      * this class.
 122:      * 
 123:      * @param prefix  the prefix (<code>null</code> not permitted).
 124:      */
 125:     public static void setTempOneTimeFilePrefix(String prefix) {
 126:         if (prefix == null) {
 127:             throw new IllegalArgumentException("Null 'prefix' argument.");   
 128:         }
 129:         ServletUtilities.tempOneTimeFilePrefix = prefix;
 130:     }
 131:     
 132:     /**
 133:      * Saves the chart as a PNG format file in the temporary directory.
 134:      *
 135:      * @param chart  the JFreeChart to be saved.
 136:      * @param width  the width of the chart.
 137:      * @param height  the height of the chart.
 138:      * @param session  the HttpSession of the client (if <code>null</code>, the
 139:      *                 temporary file is marked as "one-time" and deleted by 
 140:      *                 the {@link DisplayChart} servlet right after it is
 141:      *                 streamed to the client).
 142:      *
 143:      * @return The filename of the chart saved in the temporary directory.
 144:      *
 145:      * @throws IOException if there is a problem saving the file.
 146:      */
 147:     public static String saveChartAsPNG(JFreeChart chart, int width, int height,
 148:             HttpSession session) throws IOException {
 149:         
 150:         return ServletUtilities.saveChartAsPNG(chart, width, height, null, 
 151:                 session);
 152:         
 153:     }
 154: 
 155:     /**
 156:      * Saves the chart as a PNG format file in the temporary directory and
 157:      * populates the {@link ChartRenderingInfo} object which can be used to 
 158:      * generate an HTML image map.
 159:      *
 160:      * @param chart  the chart to be saved (<code>null</code> not permitted).
 161:      * @param width  the width of the chart.
 162:      * @param height  the height of the chart.
 163:      * @param info  the ChartRenderingInfo object to be populated 
 164:      *              (<code>null</code> permitted).
 165:      * @param session  the HttpSession of the client (if <code>null</code>, the
 166:      *                 temporary file is marked as "one-time" and deleted by 
 167:      *                 the {@link DisplayChart} servlet right after it is
 168:      *                 streamed to the client).
 169:      *
 170:      * @return The filename of the chart saved in the temporary directory.
 171:      *
 172:      * @throws IOException if there is a problem saving the file.
 173:      */
 174:     public static String saveChartAsPNG(JFreeChart chart, int width, int height,
 175:             ChartRenderingInfo info, HttpSession session) throws IOException {
 176: 
 177:         if (chart == null) {
 178:             throw new IllegalArgumentException("Null 'chart' argument.");   
 179:         }
 180:         ServletUtilities.createTempDir();
 181:         String prefix = ServletUtilities.tempFilePrefix;
 182:         if (session == null) {
 183:             prefix = ServletUtilities.tempOneTimeFilePrefix;
 184:         }
 185:         File tempFile = File.createTempFile(prefix, ".png", 
 186:                 new File(System.getProperty("java.io.tmpdir")));
 187:         ChartUtilities.saveChartAsPNG(tempFile, chart, width, height, info);
 188:         if (session != null) {
 189:             ServletUtilities.registerChartForDeletion(tempFile, session);
 190:         }
 191:         return tempFile.getName();
 192: 
 193:     }
 194: 
 195:     /**
 196:      * Saves the chart as a JPEG format file in the temporary directory.
 197:      * <p>
 198:      * SPECIAL NOTE: Please avoid using JPEG as an image format for charts,
 199:      * it is a "lossy" format that introduces visible distortions in the
 200:      * resulting image - use PNG instead.  In addition, note that JPEG output
 201:      * is supported by JFreeChart only for JRE 1.4.2 or later.
 202:      * 
 203:      * @param chart  the JFreeChart to be saved.
 204:      * @param width  the width of the chart.
 205:      * @param height  the height of the chart.
 206:      * @param session  the HttpSession of the client (if <code>null</code>, the
 207:      *                 temporary file is marked as "one-time" and deleted by 
 208:      *                 the {@link DisplayChart} servlet right after it is
 209:      *                 streamed to the client).
 210:      *
 211:      * @return The filename of the chart saved in the temporary directory.
 212:      *
 213:      * @throws IOException if there is a problem saving the file.
 214:      */
 215:     public static String saveChartAsJPEG(JFreeChart chart, int width, 
 216:                                          int height, HttpSession session) 
 217:             throws IOException {
 218: 
 219:         return ServletUtilities.saveChartAsJPEG(chart, width, height, null, 
 220:                 session);
 221:         
 222:     }
 223: 
 224:     /**
 225:      * Saves the chart as a JPEG format file in the temporary directory and
 226:      * populates the <code>ChartRenderingInfo</code> object which can be used 
 227:      * to generate an HTML image map.
 228:      * <p>
 229:      * SPECIAL NOTE: Please avoid using JPEG as an image format for charts,
 230:      * it is a "lossy" format that introduces visible distortions in the
 231:      * resulting image - use PNG instead.  In addition, note that JPEG output
 232:      * is supported by JFreeChart only for JRE 1.4.2 or later.
 233:      *
 234:      * @param chart  the chart to be saved (<code>null</code> not permitted).
 235:      * @param width  the width of the chart
 236:      * @param height  the height of the chart
 237:      * @param info  the ChartRenderingInfo object to be populated
 238:      * @param session  the HttpSession of the client (if <code>null</code>, the
 239:      *                 temporary file is marked as "one-time" and deleted by 
 240:      *                 the {@link DisplayChart} servlet right after it is
 241:      *                 streamed to the client).
 242:      *
 243:      * @return The filename of the chart saved in the temporary directory
 244:      *
 245:      * @throws IOException if there is a problem saving the file.
 246:      */
 247:     public static String saveChartAsJPEG(JFreeChart chart, int width, 
 248:             int height, ChartRenderingInfo info, HttpSession session)
 249:             throws IOException {
 250: 
 251:         if (chart == null) {
 252:             throw new IllegalArgumentException("Null 'chart' argument.");   
 253:         }
 254:         
 255:         ServletUtilities.createTempDir();
 256:         String prefix = ServletUtilities.tempFilePrefix;
 257:         if (session == null) {
 258:             prefix = ServletUtilities.tempOneTimeFilePrefix;   
 259:         }
 260:         File tempFile = File.createTempFile(prefix, ".jpeg", 
 261:                 new File(System.getProperty("java.io.tmpdir")));
 262:         ChartUtilities.saveChartAsJPEG(tempFile, chart, width, height, info);
 263:         if (session != null) {
 264:             ServletUtilities.registerChartForDeletion(tempFile, session);
 265:         }
 266:         return tempFile.getName();
 267: 
 268:     }
 269: 
 270:     /**
 271:      * Creates the temporary directory if it does not exist.  Throws a 
 272:      * <code>RuntimeException</code> if the temporary directory is 
 273:      * <code>null</code>.  Uses the system property <code>java.io.tmpdir</code> 
 274:      * as the temporary directory.  This sounds like a strange thing to do but 
 275:      * my temporary directory was not created on my default Tomcat 4.0.3 
 276:      * installation.  Could save some questions on the forum if it is created 
 277:      * when not present.
 278:      */
 279:     protected static void createTempDir() {
 280:         String tempDirName = System.getProperty("java.io.tmpdir");
 281:         if (tempDirName == null) {
 282:             throw new RuntimeException("Temporary directory system property " 
 283:                     + "(java.io.tmpdir) is null.");
 284:         }
 285: 
 286:         // create the temporary directory if it doesn't exist
 287:         File tempDir = new File(tempDirName);
 288:         if (!tempDir.exists()) {
 289:             tempDir.mkdirs();
 290:         }
 291:     }
 292: 
 293:     /**
 294:      * Adds a {@link ChartDeleter} object to the session object with the name 
 295:      * <code>JFreeChart_Deleter</code> if there is not already one bound to the 
 296:      * session and adds the filename to the list of charts to be deleted.
 297:      *
 298:      * @param tempFile  the file to be deleted.
 299:      * @param session  the HTTP session of the client.
 300:      */
 301:     protected static void registerChartForDeletion(File tempFile, 
 302:             HttpSession session) {
 303: 
 304:         //  Add chart to deletion list in session
 305:         if (session != null) {
 306:             ChartDeleter chartDeleter 
 307:                 = (ChartDeleter) session.getAttribute("JFreeChart_Deleter");
 308:             if (chartDeleter == null) {
 309:                 chartDeleter = new ChartDeleter();
 310:                 session.setAttribute("JFreeChart_Deleter", chartDeleter);
 311:             }
 312:             chartDeleter.addChart(tempFile.getName());
 313:         }
 314:         else {
 315:             System.out.println("Session is null - chart will not be deleted");
 316:         }
 317:     }
 318: 
 319:     /**
 320:      * Binary streams the specified file in the temporary directory to the
 321:      * HTTP response in 1KB chunks.
 322:      * 
 323:      * @param filename  the name of the file in the temporary directory.
 324:      * @param response  the HTTP response object.
 325:      * 
 326:      * @throws IOException  if there is an I/O problem.
 327:      */
 328:     public static void sendTempFile(String filename, 
 329:             HttpServletResponse response) throws IOException {
 330: 
 331:         File file = new File(System.getProperty("java.io.tmpdir"), filename);
 332:         ServletUtilities.sendTempFile(file, response);
 333:     }
 334: 
 335:     /**
 336:      * Binary streams the specified file to the HTTP response in 1KB chunks.
 337:      *
 338:      * @param file  the file to be streamed.
 339:      * @param response  the HTTP response object.
 340:      *
 341:      * @throws IOException if there is an I/O problem.
 342:      */
 343:     public static void sendTempFile(File file, HttpServletResponse response)
 344:             throws IOException {
 345: 
 346:         String mimeType = null;
 347:         String filename = file.getName();
 348:         if (filename.length() > 5) {
 349:             if (filename.substring(filename.length() - 5, 
 350:                     filename.length()).equals(".jpeg")) {
 351:                 mimeType = "image/jpeg";
 352:             } 
 353:             else if (filename.substring(filename.length() - 4, 
 354:                     filename.length()).equals(".png")) {
 355:                 mimeType = "image/png";
 356:             }
 357:         }
 358:         ServletUtilities.sendTempFile(file, response, mimeType);
 359:     }
 360: 
 361:     /**
 362:      * Binary streams the specified file to the HTTP response in 1KB chunks.
 363:      *
 364:      * @param file  the file to be streamed.
 365:      * @param response  the HTTP response object.
 366:      * @param mimeType  the mime type of the file, null allowed.
 367:      *
 368:      * @throws IOException if there is an I/O problem.
 369:      */
 370:     public static void sendTempFile(File file, HttpServletResponse response,
 371:                                     String mimeType) throws IOException {
 372: 
 373:         if (file.exists()) {
 374:             BufferedInputStream bis = new BufferedInputStream(
 375:                     new FileInputStream(file));
 376: 
 377:             //  Set HTTP headers
 378:             if (mimeType != null) {
 379:                 response.setHeader("Content-Type", mimeType);
 380:             }
 381:             response.setHeader("Content-Length", String.valueOf(file.length()));
 382:             SimpleDateFormat sdf = new SimpleDateFormat(
 383:                     "EEE, dd MMM yyyy HH:mm:ss z");
 384:             sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
 385:             response.setHeader("Last-Modified", 
 386:                     sdf.format(new Date(file.lastModified())));
 387: 
 388:             BufferedOutputStream bos = new BufferedOutputStream(
 389:                     response.getOutputStream());
 390:             byte[] input = new byte[1024];
 391:             boolean eof = false;
 392:             while (!eof) {
 393:                 int length = bis.read(input);
 394:                 if (length == -1) {
 395:                     eof = true;
 396:                 } 
 397:                 else {
 398:                     bos.write(input, 0, length);
 399:                 }
 400:             }
 401:             bos.flush();
 402:             bis.close();
 403:             bos.close();
 404:         }
 405:         else {
 406:             throw new FileNotFoundException(file.getAbsolutePath());
 407:         }
 408:         return;
 409:     }
 410: 
 411:     /**
 412:      * Perform a search/replace operation on a String
 413:      * There are String methods to do this since (JDK 1.4)
 414:      *
 415:      * @param inputString  the String to have the search/replace operation.
 416:      * @param searchString  the search String.
 417:      * @param replaceString  the replace String.
 418:      *
 419:      * @return The String with the replacements made.
 420:      */
 421:     public static String searchReplace(String inputString,
 422:                                        String searchString,
 423:                                        String replaceString) {
 424: 
 425:         int i = inputString.indexOf(searchString);
 426:         if (i == -1) {
 427:             return inputString;
 428:         }
 429: 
 430:         String r = "";
 431:         r += inputString.substring(0, i) + replaceString;
 432:         if (i + searchString.length() < inputString.length()) {
 433:             r += searchReplace(inputString.substring(i + searchString.length()),
 434:                     searchString, replaceString);
 435:         }
 436: 
 437:         return r;
 438:     }
 439: 
 440: }