Class ReaderToUTF8Stream

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

    public final class ReaderToUTF8Stream
    extends java.io.InputStream
    Converts the characters served by a java.io.Reader to a stream returning the data in the on-disk modified UTF-8 encoded representation used by Derby.

    Length validation is performed. If required and allowed by the target column type, truncation of blanks will also be performed.

    • Field Summary

      Fields 
      Modifier and Type Field Description
      private int blen  
      private int boff  
      private byte[] buffer
      Buffer to hold the data read from stream and converted to the modified UTF-8 format.
      private int charCount
      The number of chars encoded.
      private int charsToTruncate
      Number of characters to truncate from this stream.
      private boolean eof  
      private static int FIRST_READ
      Constant indicating the first iteration of fillBuffer.
      private StreamHeaderGenerator hdrGen
      The generator for the stream header to use for this stream.
      private int headerLength
      The length of the header.
      private int mark
      Stream mark, set through mark(int).
      private static int MARK_UNSET_OR_EXCEEDED
      Constant indicating that no mark is set in the stream, or that the read ahead limit of the mark has been exceeded.
      private boolean multipleBuffer
      Tells if the stream content is/was larger than the buffer size.
      private static int READ_BUFFER_RESERVATION
      Buffer space reserved for one 3 byte encoded char and the EOF marker.
      private int readAheadLimit
      Read ahead limit for mark, set through mark(int).
      private LimitReader reader
      Application's reader wrapped in a LimitReader.
      private static char SPACE  
      private java.lang.String typeName
      The type name for the column data is inserted into.
      private int valueLength
      If positive, length of the expected final value, after truncation if any, in characters.
    • Constructor Summary

      Constructors 
      Constructor Description
      ReaderToUTF8Stream​(java.io.Reader appReader, int valueLength, int numCharsToTruncate, java.lang.String typeName, StreamHeaderGenerator headerGenerator)
      Create a stream that will truncate trailing blanks if required/allowed.
      ReaderToUTF8Stream​(java.io.Reader appReader, int maximumLength, java.lang.String typeName, StreamHeaderGenerator headerGenerator)
      Creates a UTF-8 stream for an application reader whose length isn't known at insertion time.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      int available()
      Return an optimized version of bytes available to read from the stream.
      private boolean canTruncate()
      Determine if trailing blank truncation is allowed.
      private void checkSufficientData()
      Validate the length of the stream, take corrective action if allowed.
      void close()
      return resources
      private void fillBuffer​(int startingOffset)
      Fills the internal buffer with data read from the source stream.
      void mark​(int readAheadLimit)
      Marks the current position in the stream.
      boolean markSupported()
      Tests if this stream supports mark/reset.
      int read()
      Reads a byte from the stream.
      int read​(byte[] b, int off, int len)
      Reads up to len bytes from the stream.
      void reset()
      Repositions this stream to the position at the time the mark method was last called on this input stream.
      private void truncate()
      Attempt to truncate the stream by removing trailing blanks.
      • Methods inherited from class java.io.InputStream

        nullInputStream, read, readAllBytes, readNBytes, readNBytes, skip, transferTo
      • Methods inherited from class java.lang.Object

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

      • reader

        private LimitReader reader
        Application's reader wrapped in a LimitReader.
      • FIRST_READ

        private static final int FIRST_READ
        Constant indicating the first iteration of fillBuffer.
        See Also:
        Constant Field Values
      • READ_BUFFER_RESERVATION

        private static final int READ_BUFFER_RESERVATION
        Buffer space reserved for one 3 byte encoded char and the EOF marker.
        See Also:
        Constant Field Values
      • MARK_UNSET_OR_EXCEEDED

        private static final int MARK_UNSET_OR_EXCEEDED
        Constant indicating that no mark is set in the stream, or that the read ahead limit of the mark has been exceeded.
        See Also:
        Constant Field Values
      • buffer

        private byte[] buffer
        Buffer to hold the data read from stream and converted to the modified UTF-8 format. The initial size is dependent on whether the data value length is known (limited upwards to 32 KB), but it may grow if mark(int) is invoked.
      • boff

        private int boff
      • blen

        private int blen
      • mark

        private int mark
        Stream mark, set through mark(int).
      • readAheadLimit

        private int readAheadLimit
        Read ahead limit for mark, set through mark(int).
      • eof

        private boolean eof
      • multipleBuffer

        private boolean multipleBuffer
        Tells if the stream content is/was larger than the buffer size.
      • headerLength

        private int headerLength
        The length of the header.
      • charsToTruncate

        private final int charsToTruncate
        Number of characters to truncate from this stream. The SQL standard allows for truncation of trailing spaces for CLOB, VARCHAR and CHAR. If zero, no characters are truncated, unless the stream length exceeds the maximum length of the column we are inserting into.
      • valueLength

        private final int valueLength
        If positive, length of the expected final value, after truncation if any, in characters. If negative, the maximum length allowed in the column we are inserting into. A negative value means we are working with a stream of unknown length, inserted through one of the JDBC 4.0 "lengthless override" methods.
      • typeName

        private final java.lang.String typeName
        The type name for the column data is inserted into.
      • charCount

        private int charCount
        The number of chars encoded.
    • Constructor Detail

      • ReaderToUTF8Stream

        public ReaderToUTF8Stream​(java.io.Reader appReader,
                                  int valueLength,
                                  int numCharsToTruncate,
                                  java.lang.String typeName,
                                  StreamHeaderGenerator headerGenerator)
        Create a stream that will truncate trailing blanks if required/allowed. If the stream must be truncated, the number of blanks to truncate is specified to allow the stream to be checked for exact length, as required by JDBC 3.0. If the stream is shorter or longer than specified, an exception is thrown during read.
        Parameters:
        appReader - application reader
        valueLength - the expected length of the reader in characters (positive), or the inverse (maxColWidth * -1) of the maximum column width if the expected stream length is unknown
        numCharsToTruncate - the number of trailing blanks to truncate
        typeName - type name of the column data is inserted into
        headerGenerator - the stream header generator
      • ReaderToUTF8Stream

        public ReaderToUTF8Stream​(java.io.Reader appReader,
                                  int maximumLength,
                                  java.lang.String typeName,
                                  StreamHeaderGenerator headerGenerator)
        Creates a UTF-8 stream for an application reader whose length isn't known at insertion time.

        The application reader is coming in through one of the "lengthless overrides" added in JDBC 4.0, for instance java.sql.PreparedStatement.setCharacterStream(int,Reader). A limit is placed on the length of the application reader. If the reader exceeds the maximum length, truncation of trailing blanks is attempted. If truncation fails, an exception is thrown.

        Parameters:
        appReader - application reader
        maximumLength - maximum allowed length in number of characters for the reader, typically the maximum field size
        typeName - type name of the column data is inserted into
        headerGenerator - the stream header generator
        Throws:
        java.lang.IllegalArgumentException - if maximum length is negative
    • Method Detail

      • read

        public int read()
                 throws java.io.IOException
        Reads a byte from the stream.

        Characters read from the source stream are converted to the UTF-8 Derby specific encoding.

        Specified by:
        read in class java.io.InputStream
        Returns:
        The byte read, or -1 if the end-of-stream is reached.
        Throws:
        java.io.EOFException - if the end-of-stream has already been reached or the stream has been closed
        java.io.IOException - if reading from the source stream fails
        See Also:
        InputStream.read()
      • read

        public int read​(byte[] b,
                        int off,
                        int len)
                 throws java.io.IOException
        Reads up to len bytes from the stream.

        Characters read from the source stream are converted to the UTF-8 Derby specific encoding.

        Overrides:
        read in class java.io.InputStream
        Returns:
        The number of bytes read, or -1 if the end-of-stream is reached.
        Throws:
        java.io.EOFException - if the end-of-stream has already been reached or the stream has been closed
        java.io.IOException - if reading from the source stream fails
        See Also:
        InputStream.read(byte[],int,int)
      • fillBuffer

        private void fillBuffer​(int startingOffset)
                         throws java.io.IOException
        Fills the internal buffer with data read from the source stream.

        The characters read from the source are converted to the modified UTF-8 encoding, used as the on-disk format by Derby.

        Parameters:
        startingOffset - offset at which to start filling the buffer, used to avoid overwriting the stream header data on the first iteration
        Throws:
        DerbyIOException - if the source stream has an invalid length (different than specified), or if truncation of blanks fails
        java.io.IOException - if reading from the source stream fails
      • checkSufficientData

        private void checkSufficientData()
                                  throws java.io.IOException
        Validate the length of the stream, take corrective action if allowed. JDBC 3.0 (from tutorial book) requires that an input stream has the correct number of bytes in the stream. If the stream is too long, trailing blank truncation is attempted if allowed. If truncation fails, or is disallowed, an exception is thrown.
        Throws:
        java.io.IOException - if an errors occurs in the application stream
        DerbyIOException - if Derby finds a problem with the stream; stream is too long and cannot be truncated, or the stream length does not match the specified length
      • canTruncate

        private boolean canTruncate()
        Determine if trailing blank truncation is allowed.
      • truncate

        private void truncate()
                       throws java.io.IOException
        Attempt to truncate the stream by removing trailing blanks.
        Throws:
        java.io.IOException
      • close

        public void close()
        return resources
        Specified by:
        close in interface java.lang.AutoCloseable
        Specified by:
        close in interface java.io.Closeable
        Overrides:
        close in class java.io.InputStream
      • available

        public final int available()
        Return an optimized version of bytes available to read from the stream.

        Note, it is not exactly per java.io.InputStream#available().

        Overrides:
        available in class java.io.InputStream
      • mark

        public void mark​(int readAheadLimit)
        Marks the current position in the stream.

        Note that this stream is not marked at position zero by default (i.e. in the constructor).

        Overrides:
        mark in class java.io.InputStream
        Parameters:
        readAheadLimit - the maximum limit of bytes that can be read before the mark position becomes invalid
      • reset

        public void reset()
                   throws java.io.IOException
        Repositions this stream to the position at the time the mark method was last called on this input stream.
        Overrides:
        reset in class java.io.InputStream
        Throws:
        java.io.EOFException - if the stream has been closed
        java.io.IOException - if no mark has been set, or the read ahead limit of the mark has been exceeded
      • markSupported

        public boolean markSupported()
        Tests if this stream supports mark/reset.

        The markSupported method of ByteArrayInputStream always returns true.

        Overrides:
        markSupported in class java.io.InputStream
        Returns:
        true, mark/reset is always supported.