Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2007, 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-2007, 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: * Changes 38: * ------- 39: * 19-Aug-2002 : Version 1; 40: * 20-Apr-2003 : Added additional sendTempFile method to allow MIME type 41: * specification and modified original sendTempFile method to 42: * automatically set MIME type for JPEG and PNG files 43: * 23-Jun-2003 : Added additional sendTempFile method at the request of 44: * J?rgen Hoffman; 45: * 07-Jul-2003 : Added more header information to streamed images; 46: * 19-Aug-2003 : Forced images to be stored in the temporary directory defined 47: * by System property java.io.tmpdir, rather than default (RA); 48: * 24-Mar-2004 : Added temp filename prefix attribute (DG); 49: * 09-Mar-2005 : Added "one time" file option (DG); 50: * ------------- JFREECHART 1.0.x RELEASED ------------------------------------ 51: * 10-Jan-2006 : Updated API docs and reformatted (DG); 52: * 13-Sep-2006 : Format date in response header in English, not locale default 53: * (see bug 1557141) (DG); 54: * 55: */ 56: 57: package org.jfree.chart.servlet; 58: 59: import java.io.BufferedInputStream; 60: import java.io.BufferedOutputStream; 61: import java.io.File; 62: import java.io.FileInputStream; 63: import java.io.FileNotFoundException; 64: import java.io.IOException; 65: import java.text.SimpleDateFormat; 66: import java.util.Date; 67: import java.util.Locale; 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", Locale.ENGLISH); 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: }