/* * FreeMarker: a tool that allows Java programs to generate HTML * output using templates. * Copyright (C) 1998-2004 Benjamin Geer * Email: beroul@users.sourceforge.net * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package freemarker.template; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; import freemarker.template.cache.Cache; import freemarker.template.cache.Cacheable; /** * <p> * An application or servlet can instantiate a <code>BinaryData</code> to * retrieve a binary file. * * <p> * You can pass the filename of the binary file to the constructor, in which * case it is read in immediately. * * <p> * To retrive the binary data, call the {@link #process} method. * * <p> * To facilitate multithreading, <code>BinaryData</code> objects are immutable; * if you need to reload a binary file, you must make a new * <code>BinaryData</code> object. In most cases, it will be sufficient to let a * {@link freemarker.template.cache.Cache} do this for you. * * @see FileTemplateCache * @version $Id: BinaryData.java 1144 2005-10-09 06:31:56Z run2000 $ */ public class BinaryData implements Cacheable, Cloneable, Compileable, Serializable { /** * The binary data held by this object. * * @serial The binary data stored as a byte array */ protected byte[] dataArray; /** The cache to which this binary data object belongs (if any). */ protected transient Cache cache; /** Serialization UUID for this class. */ private static final long serialVersionUID = -17848906542414739L; /** * Constructs an empty binary object. */ public BinaryData() { } /** * Constructs a binary data object by compiling it from a file. Calls * <code>compileFromFile()</code>. * * @param filePath * the absolute path of the binary file to be compiled. * @deprecated Use the {@link InputSource} constructor instead */ public BinaryData(String filePath) throws IOException { compile(new FileInputSource(filePath)); } /** * Constructs a BinaryData object by compiling it from a file. Calls * <code>compileFromFile()</code>. * * @param file * a <code>File</code> representing the binary file to be * compiled. * @deprecated Use the {@link InputSource} constructor instead */ public BinaryData(File file) throws IOException { compile(new FileInputSource(file)); } /** * Constructs a template by compiling it from an <code>InputStream</code>. * Calls <code>compileFromStream()</code>. * * @param stream * an <code>InputStream</code> from which the template can be * read. * @deprecated Use the {@link InputSource} constructor instead */ public BinaryData(InputStream stream) throws IOException { compile(new InputSource(stream)); } /** * Clones an existing <code>BinaryData</code> instance. * * @param source * an <code>InputSource</code> from which the template can be * read. */ public BinaryData(InputSource source) throws IOException { compile(source); } /** * Clones an existing <code>BinaryData</code> instance. * * @param data * the <code>BinaryData</code> instance to be cloned */ public BinaryData(BinaryData data) { dataArray = data.dataArray; cache = data.cache; } /** * Reads and compiles a template from a file, by getting the file's * <tt>FileInputStream</tt> and using it to call * <tt>compileFromStream()</tt>, using the platform's default character * encoding. * * @param filePath * the absolute path of the template file to be compiled. * @deprecated Use the {@link #compile} method instead */ public void compileFromFile(String filePath) throws IOException { compile(new FileInputSource(filePath)); } /** * Reads and compiles a template from a file, by getting the file's * <tt>FileInputStream</tt> and using it to call * <tt>compileFromStream()</tt>, using the platform's default character * encoding. * * @param file * a <tt>File</tt> representing the template file to be compiled. * @deprecated Use the {@link #compile} method instead */ public void compileFromFile(File file) throws IOException { if (!file.exists()) { throw new FileNotFoundException("Template file " + file.getName() + " not found"); } if (!file.canRead()) { throw new IOException("Can't read from template file " + file.getName()); } compile(new FileInputSource(file)); } /** * Compiles the template from an <tt>InputStream</tt>, using the platform's * default character encoding. If the template has already been compiled, * this method does nothing. * * @param stream * an <tt>InputStream</tt> from which the template can be read. * @deprecated Use the {@link #compile} method instead */ public void compileFromStream(InputStream stream) throws IOException { compile(new InputSource(stream)); } /** * Compiles the template from an <tt>InputStream</tt>, using the specified * character encoding. If the template has already been compiled, this * method does nothing. * * @param stream * an <tt>InputStream</tt> from which the template can be read. * @param encoding * the character encoding to use. For binary data, this does * nothing. * @deprecated Use the {@link #compile} method instead */ public void compileFromStream(InputStream stream, String encoding) throws IOException { compile(new InputSource(stream, encoding)); } /** * Compiles the template from an <code>InputSource</code>. If the template * has already been compiled, this method does nothing. * * @param source * an <code>InputSource</code> from which the template can be * read. */ public void compile(InputSource source) throws IOException, IllegalArgumentException { ByteArrayOutputStream arrayStream = new ByteArrayOutputStream(8192); byte[] buffer = new byte[4096]; int bytes_read; InputStream stream = source.getInputStream(); if (stream == null) { throw new IllegalArgumentException("Cannot compile binary data from supplied InputSource"); } while ((bytes_read = stream.read(buffer)) >= 0) { arrayStream.write(buffer, 0, bytes_read); } arrayStream.close(); stream.close(); synchronized (this) { dataArray = arrayStream.toByteArray(); } } /** * Processes the binary data file, and output the resulting binary data to * an <tt>OutputStream</tt>. * * @param out * an <tt>OutputStream</tt> to output the HTML to. */ public void process(OutputStream out) { try { if (dataArray != null) { out.write(dataArray); } } catch (IOException e) { } } /** * Sets the {@link freemarker.template.cache.Cache} that this object is * stored in. <tt>IncludeInstruction</tt> objects will be able to request * this <code>Cache</code> at run-time. * * @param cache * the <code>Cache</code> that this template belongs to. */ public void setCache(Cache cache) { this.cache = cache; } /** * Retrieve the {@link freemarker.template.cache.Cache} that this object is * stored in. * * @return the <code>Cache</code> that this template belongs to. */ public Cache getCache() { return this.cache; } /** * Clones the current <code>BinaryData</code> object. * * @return a cloned instance of the current <code>BinaryData</code> object */ public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e.getMessage()); } } /** * Returns a string representation of the object. * * @return a string representation of the object. */ public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("BinaryData, "); if (dataArray == null) { buffer.append("no"); } else { buffer.append(dataArray.length); } buffer.append(" bytes."); return buffer.toString(); } }