/* * StreamableObject.java * * Created on 7 October 2006, 17:44 * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package au.org.kaizen.jdo; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * This class represents a streamable source of binary data that can either be * read from or written to a datasource. * * In short a streamable object is an object whose source of information is * contained within a InputStream either to be read from or written to the * datasource. * * It should be noted that once the class is initalised the classes stream can * not be reassigned. This is design choice as I didn't have enough knowledge * about the JDO to determine if it was possible to mark this class as been * dirty if it was updated in this fashion. * * It may possible to provide a wrapper to this object that can be used to * monitor it's state but is beyond the scope of this current implementation. * * If you wish to change the contents of a column in the database, you need to * replace the field representing the binary column with a new instance with the new * stream * * It was decided to avoid using the InputStream.avaliable call when trying to * determine the length of stream as it can't be relied on to always return an * accurate measure of the stream. * * It might seem fesiable simply to map directly to the InputStream, the JDBC * PreparedStatement needs to know the length of the stream in order to write * information to the datastore. As mentioned above, it may not be possible to * determine an accurate length of the binary stream simply by calling * InputStream.avalaibe. Ultimatly, this class over comes that issue. * * @author swhitehead */ public class StreamableObject { private InputStream stream; /** * Determines the number of bytes that are to be written to the database */ private long writeLength; /** * Creates a new instance of StreamableObject. * * This method is called by the mapping class when it retrieves the input stream * from the datasource. * * You are discouraged from calling this method if you wish to wtite the stream to * the datastore as the "getStreamLength" method will return 0 and no information * will be written. * @param stream Datasource input stream representing the binary information */ public StreamableObject(InputStream stream) { setBinaryStream(stream); } /** * Creates a new instance of StreamableObject. * * This method should be used when creating a new binary stream. This constructor * requires the stream length to be passed in as a requirement for the JDBC API * setBinaryStream call. * @param stream The new binary stream to be written to the datastore * @param writeLength The number of bytes that this stream conatins (or will contain) */ public StreamableObject(InputStream stream, long writeLength) { setBinaryStream(stream); setStreamLength(writeLength); } /** * Method for setting the binary stream. * @param stream The binary stream represented by this class */ protected void setBinaryStream(InputStream stream) { this.stream = stream; } /** * Returns the binary stream been managed by this class * @return The binary stream */ public InputStream getBinaryStream() { return stream; } /** * Sets the stream's length which is reported to the JDBC.setBinaryStream method * when the data is written to the datastore * @param length The binary length of the stream */ public void setStreamLength(long length) { writeLength = length; } /** * Returns the number of bytes that are to be written by the write stream * @return Returns the length of the binary stream */ public long getStreamLength() { return writeLength; } /** * String representation of the class * @return A string representation of the class */ public String toString() { StringBuffer sb = new StringBuffer("StreamableObject: "); if (stream == null) { sb.append("stream = null"); } else { try { sb.append("stream.avaliable = ").append(stream.available()); } catch (IOException ex) { sb.append("stream unable to determine avaliable due to error - ").append(ex.getMessage()); } } return sb.toString(); } /** * Convient method for dumping the binary stream to the supplied output stream * @param os The OutputStream to which the binary stream is to written to * @return Returns the number of bytes written * @throws java.io.IOException Throw if an IO error occurs during the write process */ public long writeToStream(OutputStream os) throws IOException { byte[] buffer = new byte[1024]; InputStream is = getBinaryStream(); int bytesRead = -1; int totalBytes = 0; while ((bytesRead = is.read(buffer)) > -1) { os.write(buffer, 0, bytesRead); totalBytes += bytesRead; } return totalBytes; } }