    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    }