Class DeferrableOutputStream

  • All Implemented Interfaces:
    java.io.Closeable, java.io.Flushable, java.lang.AutoCloseable

    public class DeferrableOutputStream
    extends java.io.OutputStream
    An OutputStream, which keeps its data in memory, until a configured threshold is reached. If that is the case, a temporary file is being created, and the in-memory data is transferred to that file. All following data will be written to that file, too. In other words: If an uploaded file is small, then it will be kept completely in memory. On the other hand, if the uploaded file's size exceeds the configured threshold, it it considered a large file, and the data is kept in a temporary file. More precisely, this output stream supports three modes of operation:
    1. threshold=-1: Always create a temporary file, even if the uploaded file is empty.
    2. threshold=0: Don't create empty, temporary files. (Create a temporary file, as soon as the first byte is written.)
    3. threshold>0: Create a temporary file, if the size exceeds the threshold, otherwise keep the file in memory.
    Technically, this is similar to DeferredFileOutputStream, which has been used in the past, except that this implementation observes a precisely specified behavior, and semantics, that match the needs of the DiskFileItem. Background: Over the various versions of commons-io, the DeferredFileOutputStream has changed semantics, and behavior more than once. (For details, see FILEUPLOAD-295)
    • Constructor Summary

      Constructors 
      Constructor Description
      DeferrableOutputStream​(int threshold, java.util.function.Supplier<java.nio.file.Path> pathSupplier, DeferrableOutputStream.Listener listener)
      Creates a new instance with the given threshold, and the given supplier for a temporary files path.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      protected java.io.OutputStream checkThreshold​(int numberOfIncomingBytes)
      Called to check, whether the threshold will be exceeded, if the given number of bytes are written to the stream.
      void close()  
      byte[] getBytes()
      Returns the data, that has been written, if the stream has been closed, and the stream is still in memory (isInMemory() returns true).
      java.io.InputStream getInputStream()
      If the stream is closed: Returns an InputStream on the data, that has been written to this stream.
      java.nio.file.Path getPath()
      Returns the output file, that has been created, if any, or null.
      long getSize()
      Returns the number of bytes, that have been written to this stream.
      DeferrableOutputStream.State getState()
      Returns the streams current state.
      int getThreshold()
      Returns the streams configured threshold.
      boolean isInMemory()
      Returns true, if this stream was never persisted, and no output file has been created.
      protected java.io.OutputStream persist()
      Create the output file, change the state to persisted, and return an OutputStream, which is writing to that file.
      void write​(byte[] buffer)  
      void write​(byte[] buffer, int offset, int len)  
      void write​(int b)  
      • Methods inherited from class java.io.OutputStream

        flush, nullOutputStream
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Constructor Detail

      • DeferrableOutputStream

        public DeferrableOutputStream​(int threshold,
                                      java.util.function.Supplier<java.nio.file.Path> pathSupplier,
                                      DeferrableOutputStream.Listener listener)
                               throws java.io.IOException
        Creates a new instance with the given threshold, and the given supplier for a temporary files path. If the threshold is -1, then the temporary file will be created immediately, and no in-memory data will be kept, at all. If the threshold is 0, then the temporary file will be created, as soon as the first byte will be written, but no in-memory data will be kept. If the threshold is > 0, then the temporary file will be created, as soon as that number of bytes have been written. Up to that point, data will be kept in an in-memory buffer.
        Parameters:
        threshold - Either of -1 (Create the temporary file immediately), 0 (Create the temporary file, as soon as data is being written for the first time), or >0 (Keep data in memory, as long as the given number of bytes is reached, then create a temporary file, and continue using that).
        pathSupplier - A supplier for the temporary files path. This supplier must not return null. The file's directory will be created, if necessary, by invoking Files.createDirectories(Path, java.nio.file.attribute.FileAttribute...).
        listener - An optional listener, which is being notified about important state changes.
        Throws:
        java.io.IOException - Creating the temporary file (in the case of threshold -1) has failed.
    • Method Detail

      • checkThreshold

        protected java.io.OutputStream checkThreshold​(int numberOfIncomingBytes)
                                               throws java.io.IOException
        Called to check, whether the threshold will be exceeded, if the given number of bytes are written to the stream. If so, persists the in-memory data by creating a new, temporary file, and writing the in-memory data to the file.
        Parameters:
        numberOfIncomingBytes - The number of bytes, which are about to be written.
        Returns:
        The actual output stream, to which the incoming data may be written. If the threshold is not yet exceeded, then this will be an internal ByteArrayOutputStream, otherwise a stream, which is writing to the temporary output file.
        Throws:
        java.io.IOException - Persisting the in-memory data to a temporary file has failed.
      • close

        public void close()
                   throws java.io.IOException
        Specified by:
        close in interface java.lang.AutoCloseable
        Specified by:
        close in interface java.io.Closeable
        Overrides:
        close in class java.io.OutputStream
        Throws:
        java.io.IOException
      • getBytes

        public byte[] getBytes()
        Returns the data, that has been written, if the stream has been closed, and the stream is still in memory (isInMemory() returns true). Otherwise, returns null.
        Returns:
        If the stream is closed (no more data can be written), and the data is still in memory (no temporary file has been created), returns the data, that has been written. Otherwise, returns null.
      • getInputStream

        public java.io.InputStream getInputStream()
                                           throws java.io.IOException
        If the stream is closed: Returns an InputStream on the data, that has been written to this stream. Otherwise, throws an IllegalStateException.
        Returns:
        An InputStream on the data, that has been written. Never null.
        Throws:
        java.lang.IllegalStateException - The stream has not yet been closed.
        java.io.IOException - Creating the InputStream has failed.
      • getPath

        public java.nio.file.Path getPath()
        Returns the output file, that has been created, if any, or null. The latter is the case, if isInMemory() returns true.
        Returns:
        The output file, that has been created, if any, or null.
      • getSize

        public long getSize()
        Returns the number of bytes, that have been written to this stream.
        Returns:
        The number of bytes, that have been written to this stream.
      • getThreshold

        public int getThreshold()
        Returns the streams configured threshold.
        Returns:
        The streams configured threshold.
      • persist

        protected java.io.OutputStream persist()
                                        throws java.io.IOException
        Create the output file, change the state to persisted, and return an OutputStream, which is writing to that file.
        Returns:
        The OutputStream, which is writing to the created, temporary file.
        Throws:
        java.io.IOException - Creating the temporary file has failed.
      • write

        public void write​(byte[] buffer)
                   throws java.io.IOException
        Overrides:
        write in class java.io.OutputStream
        Throws:
        java.io.IOException
      • write

        public void write​(byte[] buffer,
                          int offset,
                          int len)
                   throws java.io.IOException
        Overrides:
        write in class java.io.OutputStream
        Throws:
        java.io.IOException
      • write

        public void write​(int b)
                   throws java.io.IOException
        Specified by:
        write in class java.io.OutputStream
        Throws:
        java.io.IOException