001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-present, by David Gilbert 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 026 * 027 * --------------------- 028 * ServletUtilities.java 029 * --------------------- 030 * (C) Copyright 2002-present, by Richard Atkinson and Contributors. 031 * 032 * Original Author: Richard Atkinson; 033 * Contributor(s): J?rgen Hoffman; 034 * David Gilbert; 035 * Douglas Clayton; 036 * 037 */ 038 039package org.jfree.chart.servlet; 040 041import java.io.BufferedInputStream; 042import java.io.BufferedOutputStream; 043import java.io.File; 044import java.io.FileInputStream; 045import java.io.FileNotFoundException; 046import java.io.IOException; 047import java.text.SimpleDateFormat; 048import java.util.Date; 049import java.util.Locale; 050import java.util.TimeZone; 051 052import javax.servlet.http.HttpServletResponse; 053import javax.servlet.http.HttpSession; 054 055import org.jfree.chart.ChartRenderingInfo; 056import org.jfree.chart.ChartUtils; 057import org.jfree.chart.JFreeChart; 058import org.jfree.chart.util.Args; 059 060/** 061 * Utility class used for servlet related JFreeChart operations. 062 */ 063public class ServletUtilities { 064 065 /** The filename prefix. */ 066 private static String tempFilePrefix = "jfreechart-"; 067 068 /** A prefix for "one time" charts. */ 069 private static String tempOneTimeFilePrefix = "jfreechart-onetime-"; 070 071 /** 072 * Returns the prefix for the temporary file names generated by this class. 073 * 074 * @return The prefix (never {@code null}). 075 */ 076 public static String getTempFilePrefix() { 077 return ServletUtilities.tempFilePrefix; 078 } 079 080 /** 081 * Sets the prefix for the temporary file names generated by this class. 082 * 083 * @param prefix the prefix ({@code null} not permitted). 084 */ 085 public static void setTempFilePrefix(String prefix) { 086 Args.nullNotPermitted(prefix, "prefix"); 087 ServletUtilities.tempFilePrefix = prefix; 088 } 089 090 /** 091 * Returns the prefix for "one time" temporary file names generated by 092 * this class. 093 * 094 * @return The prefix. 095 */ 096 public static String getTempOneTimeFilePrefix() { 097 return ServletUtilities.tempOneTimeFilePrefix; 098 } 099 100 /** 101 * Sets the prefix for the "one time" temporary file names generated by 102 * this class. 103 * 104 * @param prefix the prefix ({@code null} not permitted). 105 */ 106 public static void setTempOneTimeFilePrefix(String prefix) { 107 Args.nullNotPermitted(prefix, "prefix"); 108 ServletUtilities.tempOneTimeFilePrefix = prefix; 109 } 110 111 /** 112 * Saves the chart as a PNG format file in the temporary directory. 113 * 114 * @param chart the JFreeChart to be saved. 115 * @param width the width of the chart. 116 * @param height the height of the chart. 117 * @param session the HttpSession of the client (if {@code null}, the 118 * temporary file is marked as "one-time" and deleted by 119 * the {@link DisplayChart} servlet right after it is 120 * streamed to the client). 121 * 122 * @return The filename of the chart saved in the temporary directory. 123 * 124 * @throws IOException if there is a problem saving the file. 125 */ 126 public static String saveChartAsPNG(JFreeChart chart, int width, int height, 127 HttpSession session) throws IOException { 128 129 return ServletUtilities.saveChartAsPNG(chart, width, height, null, 130 session); 131 132 } 133 134 /** 135 * Saves the chart as a PNG format file in the temporary directory and 136 * populates the {@link ChartRenderingInfo} object which can be used to 137 * generate an HTML image map. 138 * 139 * @param chart the chart to be saved ({@code null} not permitted). 140 * @param width the width of the chart. 141 * @param height the height of the chart. 142 * @param info the ChartRenderingInfo object to be populated 143 * ({@code null} permitted). 144 * @param session the HttpSession of the client (if {@code null}, the 145 * temporary file is marked as "one-time" and deleted by 146 * the {@link DisplayChart} servlet right after it is 147 * streamed to the client). 148 * 149 * @return The filename of the chart saved in the temporary directory. 150 * 151 * @throws IOException if there is a problem saving the file. 152 */ 153 public static String saveChartAsPNG(JFreeChart chart, int width, int height, 154 ChartRenderingInfo info, HttpSession session) throws IOException { 155 156 Args.nullNotPermitted(chart, "chart"); 157 ServletUtilities.createTempDir(); 158 String prefix = ServletUtilities.tempFilePrefix; 159 if (session == null) { 160 prefix = ServletUtilities.tempOneTimeFilePrefix; 161 } 162 File tempFile = File.createTempFile(prefix, ".png", 163 new File(System.getProperty("java.io.tmpdir"))); 164 ChartUtils.saveChartAsPNG(tempFile, chart, width, height, info); 165 if (session != null) { 166 ServletUtilities.registerChartForDeletion(tempFile, session); 167 } 168 return tempFile.getName(); 169 170 } 171 172 /** 173 * Saves the chart as a JPEG format file in the temporary directory. 174 * <p> 175 * SPECIAL NOTE: Please avoid using JPEG as an image format for charts, 176 * it is a "lossy" format that introduces visible distortions in the 177 * resulting image - use PNG instead. In addition, note that JPEG output 178 * is supported by JFreeChart only for JRE 1.4.2 or later. 179 * 180 * @param chart the JFreeChart to be saved. 181 * @param width the width of the chart. 182 * @param height the height of the chart. 183 * @param session the HttpSession of the client (if {@code null}, the 184 * temporary file is marked as "one-time" and deleted by 185 * the {@link DisplayChart} servlet right after it is 186 * streamed to the client). 187 * 188 * @return The filename of the chart saved in the temporary directory. 189 * 190 * @throws IOException if there is a problem saving the file. 191 */ 192 public static String saveChartAsJPEG(JFreeChart chart, int width, 193 int height, HttpSession session) 194 throws IOException { 195 196 return ServletUtilities.saveChartAsJPEG(chart, width, height, null, 197 session); 198 199 } 200 201 /** 202 * Saves the chart as a JPEG format file in the temporary directory and 203 * populates the {@code ChartRenderingInfo} object which can be used 204 * to generate an HTML image map. 205 * <p> 206 * SPECIAL NOTE: Please avoid using JPEG as an image format for charts, 207 * it is a "lossy" format that introduces visible distortions in the 208 * resulting image - use PNG instead. In addition, note that JPEG output 209 * is supported by JFreeChart only for JRE 1.4.2 or later. 210 * 211 * @param chart the chart to be saved ({@code null} not permitted). 212 * @param width the width of the chart 213 * @param height the height of the chart 214 * @param info the ChartRenderingInfo object to be populated 215 * @param session the HttpSession of the client (if {@code null}, the 216 * temporary file is marked as "one-time" and deleted by 217 * the {@link DisplayChart} servlet right after it is 218 * streamed to the client). 219 * 220 * @return The filename of the chart saved in the temporary directory 221 * 222 * @throws IOException if there is a problem saving the file. 223 */ 224 public static String saveChartAsJPEG(JFreeChart chart, int width, 225 int height, ChartRenderingInfo info, HttpSession session) 226 throws IOException { 227 228 Args.nullNotPermitted(chart, "chart"); 229 ServletUtilities.createTempDir(); 230 String prefix = ServletUtilities.tempFilePrefix; 231 if (session == null) { 232 prefix = ServletUtilities.tempOneTimeFilePrefix; 233 } 234 File tempFile = File.createTempFile(prefix, ".jpeg", 235 new File(System.getProperty("java.io.tmpdir"))); 236 ChartUtils.saveChartAsJPEG(tempFile, chart, width, height, info); 237 if (session != null) { 238 ServletUtilities.registerChartForDeletion(tempFile, session); 239 } 240 return tempFile.getName(); 241 242 } 243 244 /** 245 * Creates the temporary directory if it does not exist. Throws a 246 * {@code RuntimeException} if the temporary directory is 247 * {@code null}. Uses the system property {@code java.io.tmpdir} 248 * as the temporary directory. This sounds like a strange thing to do but 249 * my temporary directory was not created on my default Tomcat 4.0.3 250 * installation. Could save some questions on the forum if it is created 251 * when not present. 252 */ 253 protected static void createTempDir() { 254 String tempDirName = System.getProperty("java.io.tmpdir"); 255 if (tempDirName == null) { 256 throw new RuntimeException("Temporary directory system property " 257 + "(java.io.tmpdir) is null."); 258 } 259 260 // create the temporary directory if it doesn't exist 261 File tempDir = new File(tempDirName); 262 if (!tempDir.exists()) { 263 tempDir.mkdirs(); 264 } 265 } 266 267 /** 268 * Adds a {@link ChartDeleter} object to the session object with the name 269 * {@code JFreeChart_Deleter} if there is not already one bound to the 270 * session and adds the filename to the list of charts to be deleted. 271 * 272 * @param tempFile the file to be deleted. 273 * @param session the HTTP session of the client. 274 */ 275 protected static void registerChartForDeletion(File tempFile, 276 HttpSession session) { 277 278 // Add chart to deletion list in session 279 if (session != null) { 280 ChartDeleter chartDeleter 281 = (ChartDeleter) session.getAttribute("JFreeChart_Deleter"); 282 if (chartDeleter == null) { 283 chartDeleter = new ChartDeleter(); 284 session.setAttribute("JFreeChart_Deleter", chartDeleter); 285 } 286 chartDeleter.addChart(tempFile.getName()); 287 } 288 else { 289 System.out.println("Session is null - chart will not be deleted"); 290 } 291 } 292 293 /** 294 * Binary streams the specified file in the temporary directory to the 295 * HTTP response in 1KB chunks. 296 * 297 * @param filename the name of the file in the temporary directory. 298 * @param response the HTTP response object. 299 * 300 * @throws IOException if there is an I/O problem. 301 */ 302 public static void sendTempFile(String filename, 303 HttpServletResponse response) throws IOException { 304 305 File file = new File(System.getProperty("java.io.tmpdir"), filename); 306 ServletUtilities.sendTempFile(file, response); 307 } 308 309 /** 310 * Binary streams the specified file to the HTTP response in 1KB chunks. 311 * 312 * @param file the file to be streamed. 313 * @param response the HTTP response object. 314 * 315 * @throws IOException if there is an I/O problem. 316 */ 317 public static void sendTempFile(File file, HttpServletResponse response) 318 throws IOException { 319 320 String mimeType = null; 321 String filename = file.getName(); 322 if (filename.length() > 5) { 323 if (filename.substring(filename.length() - 5, 324 filename.length()).equals(".jpeg")) { 325 mimeType = "image/jpeg"; 326 } 327 else if (filename.substring(filename.length() - 4, 328 filename.length()).equals(".png")) { 329 mimeType = "image/png"; 330 } 331 } 332 ServletUtilities.sendTempFile(file, response, mimeType); 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 * @param mimeType the mime type of the file, null allowed. 341 * 342 * @throws IOException if there is an I/O problem. 343 */ 344 public static void sendTempFile(File file, HttpServletResponse response, 345 String mimeType) throws IOException { 346 347 if (file.exists()) { 348 BufferedInputStream bis = new BufferedInputStream( 349 new FileInputStream(file)); 350 351 // Set HTTP headers 352 if (mimeType != null) { 353 response.setHeader("Content-Type", mimeType); 354 } 355 response.setHeader("Content-Length", String.valueOf(file.length())); 356 SimpleDateFormat sdf = new SimpleDateFormat( 357 "EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH); 358 sdf.setTimeZone(TimeZone.getTimeZone("GMT")); 359 response.setHeader("Last-Modified", 360 sdf.format(new Date(file.lastModified()))); 361 362 BufferedOutputStream bos = new BufferedOutputStream( 363 response.getOutputStream()); 364 byte[] input = new byte[1024]; 365 boolean eof = false; 366 while (!eof) { 367 int length = bis.read(input); 368 if (length == -1) { 369 eof = true; 370 } 371 else { 372 bos.write(input, 0, length); 373 } 374 } 375 bos.flush(); 376 bis.close(); 377 bos.close(); 378 } 379 else { 380 throw new FileNotFoundException(file.getAbsolutePath()); 381 } 382 } 383 384 /** 385 * Perform a search/replace operation on a String 386 * There are String methods to do this since (JDK 1.4) 387 * 388 * @param inputString the String to have the search/replace operation. 389 * @param searchString the search String. 390 * @param replaceString the replace String. 391 * 392 * @return The String with the replacements made. 393 */ 394 public static String searchReplace(String inputString, 395 String searchString, 396 String replaceString) { 397 398 int i = inputString.indexOf(searchString); 399 if (i == -1) { 400 return inputString; 401 } 402 403 String r = ""; 404 r += inputString.substring(0, i) + replaceString; 405 if (i + searchString.length() < inputString.length()) { 406 r += searchReplace(inputString.substring(i + searchString.length()), 407 searchString, replaceString); 408 } 409 410 return r; 411 } 412 413}