nl_tokens: Performs internal read to the given byte buffer .
pl_tokens: @ DoesServiceRequest private synchronized int readInternal ( final byte [ ] b , final int off , int len ) throws IOException { this . checkStreamState ( ) ; // if buffer is empty do next get operation if ( ( this . currentBuffer == null || this . currentBuffer . available ( ) == 0 ) && this . currentAbsoluteReadPosition < this . streamLength ) { this . dispatchRead ( ( int ) Math . <mask> ( this . readSize , this . streamLength - this . currentAbsoluteReadPosition ) ) ; } len = Math . min ( len , this . readSize ) ; // do read from buffer final int numberOfBytesRead = this . currentBuffer . read ( b , off , len ) ; if ( numberOfBytesRead > 0 ) { this . currentAbsoluteReadPosition += numberOfBytesRead ; if ( this . validateFileMd5 ) { this . md5Digest . update ( b , off , numberOfBytesRead ) ; if ( this . currentAbsoluteReadPosition == this . streamLength ) { // Reached end of stream, validate md5. final String calculatedMd5 = Base64 . encode ( this . md5Digest . digest ( ) ) ; if ( ! calculatedMd5 . equals ( this . retrievedContentMD5Value ) ) { this . lastError = Utility . initIOException ( new StorageException ( StorageErrorCodeStrings . INVALID_MD5 , String . format ( "File data corrupted (integrity check failed), Expected value is %s, retrieved %s" , this . retrievedContentMD5Value , calculatedMd5 ) , Constants . HeaderConstants . HTTP_UNUSED_306 , null , null ) ) ; this . streamFaulted = true ; throw this . lastError ; } } } } // update markers if ( this . markExpiry > 0 && this . markedPosition + this . markExpiry < this . currentAbsoluteReadPosition ) { this . markedPosition = 0 ; this . markExpiry = 0 ; } return numberOfBytesRead ; }