Class RereadableContent

  • All Implemented Interfaces:
    Closeable, AutoCloseable
    Direct Known Subclasses:
    FileContent, MemoryContent, WrappingContent

    public abstract class RereadableContent
    extends Object
    implements Closeable
    The RereadableContent can be used when the content of an InputStream needs to be processed multiple times. Depending on its eventual size the whole content of the input stream is buffered in-memory - up to a certain threshold - or in a temporary file.

    The RereadableContent as well as the provided input streams must be closed after use! This can be ensured by adhering to the following template:

     try (RereadableContentBuilder rcb = new RereableContentBuilder();
          RereadableContent rc = rcb.data(inputStream).build())
     {
       ...
       try (InputStream is = rc.getInputStream())
       {
         ...
       }
       ...
       try (InputStream is = rc.getInputStream())
       {
         ...
       }
       ...
     }
     
    If you want to fill the builder using an OutputStream make sure to fill and close this before building:
     try (RereadableContentBuilder rcb = new RereadableContentBuilder())
     {
       ...
       try (OutputStream os = rcb.getOutputStream())
       {
         ...
       }
       ...
       try (RereadableContent rc = rcb.build())
       {
         ...
       }
     }
     
    You can also let the RereadableContent or the InputStreams get out of the block structure. But make sure to Closeable.close() them all.
     
     RereadableContent rc;
     try (RereadableContentBuilder rcb = new RereadableContentBuilder())
     {
       ...
       try (OutputStream os = rcb.getOutputStream())
       {
         ...
       }
       rc = rbc.build();
     }
     ...
     InputStream is1 = rc.getInputStream())
     ...
     InputStream is2 = input.getInputStream())
     ...
     // Just make sure to close them all (in arbitrary order).
     is1.close();
     ...
     rc.close();
     ...
     is2.close();
     ...
     
     
    All InputStream instances created by this class will be AttributedInputStream also providing the size and the SHA-512 hash of the stream data. The created streams will be tracked. The RereadableContent will not be closed when at least one of its input streams is still in use (has not been closed). It is ensured that closing will be done by the last active input stream (or by the RereadableContent). Also all of these will close in a cleanup to make sure that they will be really closed.

    This class is thread-safe.

    • Field Detail

      • size

        protected final long size
        The size of the content.
      • sha512hash

        protected final byte[] sha512hash
        The SHA-512 hash of the content.
      • existingStreams

        protected final Collection<Object> existingStreams
        All streams that have been created by this RereadableContent including itself are identified by an arbitrary Object. They have a clean-up task used for InputStream.close() as well as post-mortem action. The task removes the Object and the last one in the collection performs cleaning up the RereadableContent, for instance deleting the temporary file.
      • finalCleanup

        protected final Closeable finalCleanup
        The final clean-up to be executed after all streams and this RereadableContent have been closed/cleaned up.
      • cleanup

        protected final Cleanup<IOException> cleanup
        The clean-up called as post-mortem action of this RereadableContent. Since this is the same logic, it is also used by close().
    • Constructor Detail

      • RereadableContent

        protected RereadableContent​(long size,
                                    byte[] sha512hash,
                                    Closeable finalCleanup)
        Creates a new RereadableContent for the designated data.
        Parameters:
        size - The size of the content.
        sha512hash - The SHA-512 hash of the content.
        finalCleanup - The final clean-up to be executed after all streams and the RereadableContent have been closed/cleaned up.
      • RereadableContent

        protected RereadableContent​(RereadableContent wrapped)
                             throws IOException
        Creates a new RereadableContent wrapping the designated RereadableContent and creating a new input stream to keep the wrapped RereadableContent alive.
        Parameters:
        wrapped - The wrapped RereadableContent.
        Throws:
        IOException - If creating a new input stream from the designated RereadableContent fails, an IOException will be thrown.
    • Method Detail

      • getSize

        public long getSize()
        Gets the size of the content.
        Returns:
        The size of the content.
      • getSHA512Hash

        public byte[] getSHA512Hash()
        Gets the SHA—512 hash of the content.
        Returns:
        The SHA-512 hash of the content.
      • getInputStream

        public AttributedInputStream getInputStream()
                                             throws IOException
        Gets an input stream for the data. This method may be called multiple times. The returned stream must be closed properly after use!
        Closing will not affect the InputStream.
        Returns:
        An input stream for the data. The caller is responsible for closing.
        Throws:
        IOException - If there are problems creating a new input stream for the data or this RereadableContent has already been closed, an IOException will be thrown.
      • createInputStream

        protected abstract InputStream createInputStream()
                                                  throws IOException
        Creates a new input stream for the content.
        Returns:
        A new input stream for the content. The caller is responsible for closing.
        Throws:
        IOException - If there are problems creating a new input stream for the content, an IOException will be thrown.
      • close

        public final void close()
                         throws IOException
        Closes the underlying stream or deletes the underlying file if there is no unclosed getInputStream(). If there are input streams of this RereadableContent that have not been closed yet, closing deferred until closing the last one of these input streams.
        Specified by:
        close in interface AutoCloseable
        Specified by:
        close in interface Closeable
        Throws:
        IOException - If closing or deleting fails, an IOException will be thrown.
      • hashCode

        public int hashCode()
        Overrides:
        hashCode in class Object
      • getSize

        public static Long getSize​(InputStream is)
        Gets the size of the designated input stream in case it is provided via RRC_INPUT_STREAM_SIZE, null otherwise.
        Parameters:
        is - The input stream for which to get the size (from the corresponding attribute).
        Returns:
        The value of the size attribute of the designated input stream or null if not available.