001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jfreechart/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 025 * in the United States and other countries.] 026 * 027 * --------------------- 028 * ServletUtilities.java 029 * --------------------- 030 * (C) Copyright 2002-2005, by Richard Atkinson and Contributors. 031 * 032 * Original Author: Richard Atkinson; 033 * Contributor(s): J?rgen Hoffman; 034 * David Gilbert (for Object Refinery Limited); 035 * Douglas Clayton; 036 * 037 * $Id: ServletUtilities.java,v 1.3.2.1 2005/10/25 20:58:06 mungady Exp $ 038 * 039 * Changes 040 * ------- 041 * 19-Aug-2002 : Version 1; 042 * 20-Apr-2003 : Added additional sendTempFile method to allow MIME type 043 * specification and modified original sendTempFile method to 044 * automatically set MIME type for JPEG and PNG files 045 * 23-Jun-2003 : Added additional sendTempFile method at the request of 046 * J?rgen Hoffman; 047 * 07-Jul-2003 : Added more header information to streamed images; 048 * 19-Aug-2003 : Forced images to be stored in the temporary directory defined 049 * by System property java.io.tmpdir, rather than default (RA); 050 * 24-Mar-2004 : Added temp filename prefix attribute (DG); 051 * 09-Mar-2005 : Added "one time" file option (DG); 052 * 053 */ 054 055 package org.jfree.chart.servlet; 056 057 import java.io.BufferedInputStream; 058 import java.io.BufferedOutputStream; 059 import java.io.File; 060 import java.io.FileInputStream; 061 import java.io.FileNotFoundException; 062 import java.io.IOException; 063 import java.text.SimpleDateFormat; 064 import java.util.Date; 065 import java.util.TimeZone; 066 067 import javax.servlet.http.HttpServletResponse; 068 import javax.servlet.http.HttpSession; 069 070 import org.jfree.chart.ChartRenderingInfo; 071 import org.jfree.chart.ChartUtilities; 072 import org.jfree.chart.JFreeChart; 073 074 /** 075 * Utility class used for servlet related JFreeChart operations. 076 * 077 * @author Richard Atkinson 078 */ 079 public class ServletUtilities { 080 081 /** The filename prefix. */ 082 private static String tempFilePrefix = "jfreechart-"; 083 084 /** A prefix for "one time" charts. */ 085 private static String tempOneTimeFilePrefix = "jfreechart-onetime-"; 086 087 /** 088 * Returns the prefix for the temporary file names generated by this class. 089 * 090 * @return The prefix (never <code>null</code>). 091 */ 092 public static String getTempFilePrefix() { 093 return ServletUtilities.tempFilePrefix; 094 } 095 096 /** 097 * Sets the prefix for the temporary file names generated by this class. 098 * 099 * @param prefix the prefix (<code>null</code> not permitted). 100 */ 101 public static void setTempFilePrefix(String prefix) { 102 if (prefix == null) { 103 throw new IllegalArgumentException("Null 'prefix' argument."); 104 } 105 ServletUtilities.tempFilePrefix = prefix; 106 } 107 108 /** 109 * Returns the prefix for "one time" temporary file names generated by 110 * this class. 111 * 112 * @return The prefix. 113 */ 114 public static String getTempOneTimeFilePrefix() { 115 return ServletUtilities.tempOneTimeFilePrefix; 116 } 117 118 /** 119 * Sets the prefix for the "one time" temporary file names generated by 120 * this class. 121 * 122 * @param prefix the prefix (<code>null</code> not permitted). 123 */ 124 public static void setTempOneTimeFilePrefix(String prefix) { 125 if (prefix == null) { 126 throw new IllegalArgumentException("Null 'prefix' argument."); 127 } 128 ServletUtilities.tempOneTimeFilePrefix = prefix; 129 } 130 131 /** 132 * Saves the chart as a PNG format file in the temporary directory. 133 * 134 * @param chart the JFreeChart to be saved. 135 * @param width the width of the chart. 136 * @param height the height of the chart. 137 * @param session the HttpSession of the client (if <code>null</code>, the 138 * temporary file is marked as "one-time" and deleted by 139 * the {@link DisplayChart} servlet right after it is 140 * streamed to the client). 141 * 142 * @return The filename of the chart saved in the temporary directory. 143 * 144 * @throws IOException if there is a problem saving the file. 145 */ 146 public static String saveChartAsPNG(JFreeChart chart, int width, int height, 147 HttpSession session) 148 throws IOException { 149 150 return ServletUtilities.saveChartAsPNG( 151 chart, width, height, null, session 152 ); 153 154 } 155 156 /** 157 * Saves the chart as a PNG format file in the temporary directory and 158 * populates the {@link ChartRenderingInfo} object which can be used to 159 * generate an HTML image map. 160 * 161 * @param chart the chart to be saved (<code>null</code> not permitted). 162 * @param width the width of the chart. 163 * @param height the height of the chart. 164 * @param info the ChartRenderingInfo object to be populated 165 * (<code>null</code> permitted). 166 * @param session the HttpSession of the client (if <code>null</code>, the 167 * temporary file is marked as "one-time" and deleted by 168 * the {@link DisplayChart} servlet right after it is 169 * streamed to the client). 170 * 171 * @return The filename of the chart saved in the temporary directory. 172 * 173 * @throws IOException if there is a problem saving the file. 174 */ 175 public static String saveChartAsPNG(JFreeChart chart, int width, int height, 176 ChartRenderingInfo info, 177 HttpSession session) 178 throws IOException { 179 180 if (chart == null) { 181 throw new IllegalArgumentException("Null 'chart' argument."); 182 } 183 ServletUtilities.createTempDir(); 184 String prefix = ServletUtilities.tempFilePrefix; 185 if (session == null) { 186 prefix = ServletUtilities.tempOneTimeFilePrefix; 187 } 188 File tempFile = File.createTempFile( 189 prefix, ".png", new File(System.getProperty("java.io.tmpdir")) 190 ); 191 ChartUtilities.saveChartAsPNG(tempFile, chart, width, height, info); 192 if (session != null) { 193 ServletUtilities.registerChartForDeletion(tempFile, session); 194 } 195 return tempFile.getName(); 196 197 } 198 199 /** 200 * Saves the chart as a JPEG format file in the temporary directory. 201 * 202 * @param chart the JFreeChart to be saved. 203 * @param width the width of the chart. 204 * @param height the height of the chart. 205 * @param session the HttpSession of the client (if <code>null</code>, the 206 * temporary file is marked as "one-time" and deleted by 207 * the {@link DisplayChart} servlet right after it is 208 * streamed to the client). 209 * 210 * @return The filename of the chart saved in the temporary directory. 211 * 212 * @throws IOException if there is a problem saving the file. 213 */ 214 public static String saveChartAsJPEG(JFreeChart chart, int width, 215 int height, HttpSession session) 216 throws IOException { 217 218 return ServletUtilities.saveChartAsJPEG( 219 chart, width, height, null, session 220 ); 221 222 } 223 224 /** 225 * Saves the chart as a JPEG format file in the temporary directory and 226 * populates the ChartRenderingInfo object which can be used to generate 227 * an HTML image map. 228 * 229 * @param chart the chart to be saved (<code>null</code> not permitted). 230 * @param width the width of the chart 231 * @param height the height of the chart 232 * @param info the ChartRenderingInfo object to be populated 233 * @param session the HttpSession of the client (if <code>null</code>, the 234 * temporary file is marked as "one-time" and deleted by 235 * the {@link DisplayChart} servlet right after it is 236 * streamed to the client). 237 * 238 * @return The filename of the chart saved in the temporary directory 239 * 240 * @throws IOException if there is a problem saving the file. 241 */ 242 public static String saveChartAsJPEG(JFreeChart chart, int width, 243 int height, ChartRenderingInfo info, 244 HttpSession session) 245 throws IOException { 246 247 if (chart == null) { 248 throw new IllegalArgumentException("Null 'chart' argument."); 249 } 250 251 ServletUtilities.createTempDir(); 252 String prefix = ServletUtilities.tempFilePrefix; 253 if (session == null) { 254 prefix = ServletUtilities.tempOneTimeFilePrefix; 255 } 256 File tempFile = File.createTempFile( 257 prefix, ".jpeg", new File(System.getProperty("java.io.tmpdir")) 258 ); 259 ChartUtilities.saveChartAsJPEG(tempFile, chart, width, height, info); 260 if (session != null) { 261 ServletUtilities.registerChartForDeletion(tempFile, session); 262 } 263 return tempFile.getName(); 264 265 } 266 267 /** 268 * Creates the temporary directory if it does not exist. Throws a 269 * <code>RuntimeException</code> if the temporary directory is 270 * <code>null</code>. Uses the system property <code>java.io.tmpdir</code> 271 * as the temporary directory. This sounds like a strange thing to do but 272 * my temporary directory was not created on my default Tomcat 4.0.3 273 * installation. Could save some questions on the forum if it is created 274 * when not present. 275 */ 276 protected static void createTempDir() { 277 String tempDirName = System.getProperty("java.io.tmpdir"); 278 if (tempDirName == null) { 279 throw new RuntimeException( 280 "Temporary directory system property (java.io.tmpdir) is null." 281 ); 282 } 283 284 // create the temporary directory if it doesn't exist 285 File tempDir = new File(tempDirName); 286 if (!tempDir.exists()) { 287 tempDir.mkdirs(); 288 } 289 } 290 291 /** 292 * Adds a {@link ChartDeleter} object to the session object with the name 293 * <code>JFreeChart_Deleter</code> if there is not already one bound to the 294 * session and adds the filename to the list of charts to be deleted. 295 * 296 * @param tempFile the file to be deleted. 297 * @param session the HTTP session of the client. 298 */ 299 protected static void registerChartForDeletion(File tempFile, 300 HttpSession session) { 301 302 // Add chart to deletion list in session 303 if (session != null) { 304 ChartDeleter chartDeleter 305 = (ChartDeleter) session.getAttribute("JFreeChart_Deleter"); 306 if (chartDeleter == null) { 307 chartDeleter = new ChartDeleter(); 308 session.setAttribute("JFreeChart_Deleter", chartDeleter); 309 } 310 chartDeleter.addChart(tempFile.getName()); 311 } 312 else { 313 System.out.println("Session is null - chart will not be deleted"); 314 } 315 } 316 317 /** 318 * Binary streams the specified file in the temporary directory to the 319 * HTTP response in 1KB chunks. 320 * 321 * @param filename the name of the file in the temporary directory. 322 * @param response the HTTP response object. 323 * 324 * @throws IOException if there is an I/O problem. 325 */ 326 public static void sendTempFile(String filename, 327 HttpServletResponse response) 328 throws IOException { 329 330 File file = new File(System.getProperty("java.io.tmpdir"), filename); 331 ServletUtilities.sendTempFile(file, response); 332 } 333 334 /** 335 * Binary streams the specified file to the HTTP response in 1KB chunks. 336 * 337 * @param file the file to be streamed. 338 * @param response the HTTP response object. 339 * 340 * @throws IOException if there is an I/O problem. 341 */ 342 public static void sendTempFile(File file, HttpServletResponse response) 343 throws IOException { 344 345 String mimeType = null; 346 String filename = file.getName(); 347 if (filename.length() > 5) { 348 if (filename.substring(filename.length() - 5, 349 filename.length()).equals(".jpeg")) { 350 mimeType = "image/jpeg"; 351 } 352 else if (filename.substring(filename.length() - 4, 353 filename.length()).equals(".png")) { 354 mimeType = "image/png"; 355 } 356 } 357 ServletUtilities.sendTempFile(file, response, mimeType); 358 } 359 360 /** 361 * Binary streams the specified file to the HTTP response in 1KB chunks. 362 * 363 * @param file the file to be streamed. 364 * @param response the HTTP response object. 365 * @param mimeType the mime type of the file, null allowed. 366 * 367 * @throws IOException if there is an I/O problem. 368 */ 369 public static void sendTempFile(File file, HttpServletResponse response, 370 String mimeType) throws IOException { 371 372 if (file.exists()) { 373 BufferedInputStream bis = new BufferedInputStream( 374 new FileInputStream(file) 375 ); 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 ); 385 sdf.setTimeZone(TimeZone.getTimeZone("GMT")); 386 response.setHeader( 387 "Last-Modified", sdf.format(new Date(file.lastModified())) 388 ); 389 390 BufferedOutputStream bos = new BufferedOutputStream( 391 response.getOutputStream() 392 ); 393 byte[] input = new byte[1024]; 394 boolean eof = false; 395 while (!eof) { 396 int length = bis.read(input); 397 if (length == -1) { 398 eof = true; 399 } 400 else { 401 bos.write(input, 0, length); 402 } 403 } 404 bos.flush(); 405 bis.close(); 406 bos.close(); 407 } 408 else { 409 throw new FileNotFoundException(file.getAbsolutePath()); 410 } 411 return; 412 } 413 414 /** 415 * Perform a search/replace operation on a String 416 * There are String methods to do this since (JDK 1.4) 417 * 418 * @param inputString the String to have the search/replace operation. 419 * @param searchString the search String. 420 * @param replaceString the replace String. 421 * 422 * @return The String with the replacements made. 423 */ 424 public static String searchReplace(String inputString, 425 String searchString, 426 String replaceString) { 427 428 int i = inputString.indexOf(searchString); 429 if (i == -1) { 430 return inputString; 431 } 432 433 String r = ""; 434 r += inputString.substring(0, i) + replaceString; 435 if (i + searchString.length() < inputString.length()) { 436 r += searchReplace( 437 inputString.substring(i + searchString.length()), 438 searchString, replaceString 439 ); 440 } 441 442 return r; 443 } 444 445 }