javax.annotation.WillNotClose Java Examples

The following examples show how to use javax.annotation.WillNotClose. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Base16Codec.java    From ph-commons with Apache License 2.0 6 votes vote down vote up
public void decode (@Nullable final byte [] aEncodedBuffer,
                    @Nonnegative final int nOfs,
                    @Nonnegative final int nLen,
                    @Nonnull @WillNotClose final OutputStream aOS)
{
  if (aEncodedBuffer == null)
    return;

  try (final NonBlockingByteArrayInputStream aIS = new NonBlockingByteArrayInputStream (aEncodedBuffer,
                                                                                        nOfs,
                                                                                        nLen,
                                                                                        false))
  {
    decode (aIS, aOS);
  }
}
 
Example #2
Source File: ChannelHelper.java    From ph-commons with Apache License 2.0 6 votes vote down vote up
/**
 * Channel copy method 2. This method performs the same copy, but assures the
 * temporary buffer is empty before reading more data. This never requires
 * data copying but may result in more systems calls. No post-loop cleanup is
 * needed because the buffer will be empty when the loop is exited.<br>
 * Source: Java NIO, page 60
 *
 * @param aSrc
 *        Source channel. May not be <code>null</code>. Is not closed after
 *        the operation.
 * @param aDest
 *        Destination channel. May not be <code>null</code>. Is not closed
 *        after the operation.
 * @return The number of bytes written.
 */
private static long _channelCopy2 (@Nonnull @WillNotClose final ReadableByteChannel aSrc,
                                   @Nonnull @WillNotClose final WritableByteChannel aDest) throws IOException
{
  long nBytesWritten = 0;
  final ByteBuffer aBuffer = ByteBuffer.allocateDirect (16 * 1024);
  while (aSrc.read (aBuffer) != -1)
  {
    // Prepare the buffer to be drained
    aBuffer.flip ();

    // Make sure that the buffer was fully drained
    while (aBuffer.hasRemaining ())
      nBytesWritten += aDest.write (aBuffer);

    // Make the buffer empty, ready for filling
    aBuffer.clear ();
  }
  return nBytesWritten;
}
 
Example #3
Source File: FlateCodec.java    From ph-commons with Apache License 2.0 6 votes vote down vote up
public void decode (@Nullable final byte [] aEncodedBuffer,
                    @Nonnegative final int nOfs,
                    @Nonnegative final int nLen,
                    @Nonnull @WillNotClose final OutputStream aOS)
{
  if (aEncodedBuffer == null || nLen == 0)
    return;

  if (!isZlibHead (aEncodedBuffer, nOfs, nLen))
    LOGGER.warn ("ZLib header not found");

  try (
      final InflaterInputStream aDecodeIS = new InflaterInputStream (new NonBlockingByteArrayInputStream (aEncodedBuffer,
                                                                                                          nOfs,
                                                                                                          nLen)))
  {
    if (StreamHelper.copyInputStreamToOutputStream (aDecodeIS, aOS).isFailure ())
      throw new DecodeException ("Failed to flate decode!");
  }
  catch (final IOException ex)
  {
    throw new DecodeException ("Failed to flate decode", ex);
  }
}
 
Example #4
Source File: GZIPCodec.java    From ph-commons with Apache License 2.0 6 votes vote down vote up
public void decode (@Nullable final byte [] aEncodedBuffer,
                    @Nonnegative final int nOfs,
                    @Nonnegative final int nLen,
                    @Nonnull @WillNotClose final OutputStream aOS)
{
  if (aEncodedBuffer == null || nLen == 0)
    return;

  try (final GZIPInputStream aDecodeIS = new GZIPInputStream (new NonBlockingByteArrayInputStream (aEncodedBuffer,
                                                                                                   nOfs,
                                                                                                   nLen)))
  {
    if (StreamHelper.copyInputStreamToOutputStream (aDecodeIS, aOS).isFailure ())
      throw new DecodeException ("Failed to GZIP decode!");
  }
  catch (final IOException ex)
  {
    throw new DecodeException ("Failed to GZIP encode", ex);
  }
}
 
Example #5
Source File: Base64Codec.java    From ph-commons with Apache License 2.0 6 votes vote down vote up
public void encode (@Nullable final byte [] aDecodedBuffer,
                    @Nonnegative final int nOfs,
                    @Nonnegative final int nLen,
                    @Nonnull @WillNotClose final OutputStream aOS)
{
  if (aDecodedBuffer == null || nLen == 0)
    return;

  try (final Base64OutputStream aB64OS = createBase64OutputStream (aOS))
  {
    aB64OS.write (aDecodedBuffer, nOfs, nLen);
  }
  catch (final IOException ex)
  {
    throw new EncodeException ("Failed to encode Base64", ex);
  }
}
 
Example #6
Source File: FileChannelHelper.java    From ph-commons with Apache License 2.0 6 votes vote down vote up
@Nullable
private static InputStream _getMappedInputStream (@Nonnull @WillNotClose final FileChannel aChannel,
                                                  @Nonnull final File aFile)
{
  try
  {
    final MappedByteBuffer aBuffer = aChannel.map (MapMode.READ_ONLY, 0, aChannel.size ());
    if (LOGGER.isInfoEnabled ())
      LOGGER.info ("Created memory mapped input stream for " + aFile);
    return new ByteBufferInputStream (aBuffer);
  }
  catch (final IOException ex)
  {
    LOGGER.warn ("Failed to create memory mapped input stream for " + aFile, ex);
    return null;
  }
}
 
Example #7
Source File: QuotedPrintableCodec.java    From ph-commons with Apache License 2.0 6 votes vote down vote up
public void encode (@Nullable final byte [] aDecodedBuffer,
                    @Nonnegative final int nOfs,
                    @Nonnegative final int nLen,
                    @Nonnull @WillNotClose final OutputStream aOS)
{
  if (aDecodedBuffer == null || nLen == 0)
    return;

  try
  {
    for (int i = 0; i < nLen; ++i)
    {
      final int b = aDecodedBuffer[nOfs + i] & 0xff;
      if (m_aPrintableChars.get (b))
        aOS.write (b);
      else
        writeEncodeQuotedPrintableByte (b, aOS);
    }
  }
  catch (final IOException ex)
  {
    throw new EncodeException ("Failed to encode quoted-printable", ex);
  }
}
 
Example #8
Source File: Base16Codec.java    From ph-commons with Apache License 2.0 6 votes vote down vote up
public void encode (@Nonnull @WillNotClose final InputStream aDecodedIS,
                    @Nonnull @WillNotClose final OutputStream aOS)
{
  ValueEnforcer.notNull (aDecodedIS, "DecodedInputStream");
  ValueEnforcer.notNull (aOS, "OutputStream");

  try
  {
    int nByte;
    while ((nByte = aDecodedIS.read ()) != -1)
    {
      aOS.write (StringHelper.getHexChar ((nByte & 0xf0) >> 4));
      aOS.write (StringHelper.getHexChar (nByte & 0x0f));
    }
  }
  catch (final IOException ex)
  {
    throw new EncodeException ("Failed to encode Base16", ex);
  }
}
 
Example #9
Source File: Base16Codec.java    From ph-commons with Apache License 2.0 6 votes vote down vote up
public void encode (@Nullable final byte [] aDecodedBuffer,
                    @Nonnegative final int nOfs,
                    @Nonnegative final int nLen,
                    @Nonnull @WillNotClose final OutputStream aOS)
{
  if (aDecodedBuffer == null || nLen == 0)
    return;

  try (final NonBlockingByteArrayInputStream aIS = new NonBlockingByteArrayInputStream (aDecodedBuffer,
                                                                                        nOfs,
                                                                                        nLen,
                                                                                        false))
  {
    encode (aIS, aOS);
  }
}
 
Example #10
Source File: Util.java    From spotbugs with GNU Lesser General Public License v2.1 6 votes vote down vote up
@SuppressFBWarnings("OS_OPEN_STREAM")
public static String getXMLType(@WillNotClose InputStream in) throws IOException {
    if (!in.markSupported()) {
        throw new IllegalArgumentException("Input stream does not support mark");
    }

    in.mark(5000);
    try {
        BufferedReader r = new BufferedReader(Util.getReader(in), 2000);

        while (true) {
            String s = r.readLine();
            if (s == null) {
                break;
            }
            Matcher m = tag.matcher(s);
            if (m.find()) {
                return m.group(1);
            }
        }
        throw new IOException("Didn't find xml tag");
    } finally {
        in.reset();
    }

}
 
Example #11
Source File: SortedBugCollection.java    From spotbugs with GNU Lesser General Public License v2.1 5 votes vote down vote up
private static void checkInputStream(@WillNotClose InputStream in) throws IOException {
    if (!in.markSupported()) {
        return;
    }

    byte[] buf = new byte[200];
    in.mark(buf.length);

    int numRead = 0;

    boolean isEOF = false;
    while (numRead < buf.length && !isEOF) {
        int n = in.read(buf, numRead, buf.length - numRead);
        if (n < 0) {
            isEOF = true;
        } else {
            numRead += n;
        }
    }

    in.reset();

    try (BufferedReader reader = new BufferedReader(Util.getReader(new ByteArrayInputStream(buf)))) {
        String line;
        while ((line = reader.readLine()) != null) {
            if (line.startsWith("<BugCollection")) {
                return;
            }
        }
    }

    throw new IOException("XML does not contain saved bug data");
}
 
Example #12
Source File: RydeCompression.java    From nomulus with Apache License 2.0 5 votes vote down vote up
/**
 * Creates an OutputStream that compresses the data.
 *
 * <p>TODO(b/110465964): document where the input comes from / output goes to. Something like
 * documenting that os is the result of openEncryptor and the result goes into openFileEncoder.
 */
@CheckReturnValue
static ImprovedOutputStream openCompressor(@WillNotClose OutputStream os) {
  try {
    return new ImprovedOutputStream(
        "RydeCompressor",
        new PGPCompressedDataGenerator(COMPRESSION_ALGORITHM).open(os, new byte[BUFFER_SIZE]));
  } catch (IOException | PGPException e) {
    throw new RuntimeException(e);
  }
}
 
Example #13
Source File: LZVNBlockHeader.java    From InflatableDonkey with MIT License 5 votes vote down vote up
@Nonnull
LZVNBlockHeader load(@WillNotClose ReadableByteChannel ch) throws IOException {
    bb.rewind();
    IO.readFully(ch, bb).flip();

    nRawBytes = bb.getInt();
    nPayloadBytes = bb.getInt();

    return this;
}
 
Example #14
Source File: URLCodec.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
public void encode (@Nullable final byte [] aDecodedBuffer,
                    @Nonnegative final int nOfs,
                    @Nonnegative final int nLen,
                    @Nonnull @WillNotClose final OutputStream aOS)
{
  if (aDecodedBuffer == null || nLen == 0)
    return;

  try
  {
    for (int i = 0; i < nLen; ++i)
    {
      final int b = aDecodedBuffer[nOfs + i] & 0xff;
      if (m_aPrintableChars.get (b))
      {
        if (b == SPACE)
          aOS.write (PLUS);
        else
          aOS.write (b);
      }
      else
      {
        writeEncodedURLByte (b, aOS);
      }
    }
  }
  catch (final IOException ex)
  {
    throw new EncodeException ("Failed to encode URL", ex);
  }
}
 
Example #15
Source File: StreamHelper.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
private static void _readUntilEOF (@Nonnull @WillNotClose final Reader aReader,
                                   @Nonnull final char [] aBuffer,
                                   @Nonnull final ObjIntConsumer <? super char []> aConsumer) throws IOException
{
  ValueEnforcer.notNull (aReader, "Reader");
  ValueEnforcer.notNull (aBuffer, "Buffer");
  ValueEnforcer.notNull (aConsumer, "Consumer");

  int nCharsRead;
  // Potentially blocking read
  while ((nCharsRead = aReader.read (aBuffer, 0, aBuffer.length)) > -1)
    aConsumer.accept (aBuffer, nCharsRead);
}
 
Example #16
Source File: ProcessAssistant.java    From InflatableDonkey with MIT License 5 votes vote down vote up
@Nonnull
public static InputStream newPipedInputStream(ProcessBuilder pb, @WillNotClose InputStream is) throws IOException {
    Process p = pb.start();
    ProcessInputStream pis = new ProcessInputStream(p);
    new Thread(() -> ProcessInputStream.pipe(is, p.getOutputStream(), new byte[16384], pis::error))
            .start();
    return pis;
}
 
Example #17
Source File: RydeTar.java    From nomulus with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a new {@link ImprovedOutputStream} that creates a tar archive with a single file.
 *
 * @param os is the upstream {@link OutputStream} which is not closed by this object
 * @param expectedSize is the length in bytes of the one file, which you will write to this object
 * @param modified is the {@link PosixTarHeader.Builder#setMtime mtime} you want to set
 * @param filename is the name of the one file that will be contained in this archive
 */
@CheckReturnValue
static ImprovedOutputStream openTarWriter(
    @WillNotClose OutputStream os, long expectedSize, String filename, DateTime modified) {

  checkArgument(expectedSize >= 0);
  checkArgument(filename.endsWith(".xml"),
      "Ryde expects tar archive to contain a filename with an '.xml' extension.");
  try {
    os.write(new PosixTarHeader.Builder()
        .setName(filename)
        .setSize(expectedSize)
        .setMtime(modified)
        .build()
        .getBytes());
    return new ImprovedOutputStream("RydeTarWriter", os) {
      /** Writes the end of archive marker. */
      @Override
      public void onClose() throws IOException {
        if (getBytesWritten() != expectedSize) {
          throw new IOException(
              String.format(
                  "RydeTarOutputStream expected %,d bytes, but got %,d bytes",
                  expectedSize, getBytesWritten()));
        }
        // Round up to a 512-byte boundary and another 1024-bytes to indicate end of archive.
        out.write(new byte[1024 + 512 - (int) (getBytesWritten() % 512L)]);
      }
    };
  } catch (IOException e) {
    throw new RuntimeException(e);
  }
}
 
Example #18
Source File: ProcessAssistant.java    From InflatableDonkey with MIT License 5 votes vote down vote up
public static long copy(@WillNotClose InputStream is, @WillNotClose OutputStream os, byte[] buffer) throws IOException {
    long n = 0;
    int read;
    while ((read = is.read(buffer)) != -1) {
        os.write(buffer, 0, read);
        n += read;
    }
    return n;
}
 
Example #19
Source File: StreamHelper.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
@Nonnegative
private static long _copyInputStreamToOutputStreamWithLimit (@Nonnull @WillNotClose final InputStream aIS,
                                                             @Nonnull @WillNotClose final OutputStream aOS,
                                                             @Nonnull final byte [] aBuffer,
                                                             @Nonnegative final long nLimit) throws IOException
{
  final int nBufferLength = aBuffer.length;
  long nRest = nLimit;
  long nTotalBytesWritten = 0;
  while (true)
  {
    // if nRest is smaller than aBuffer.length, which is an int, it is safe to
    // cast nRest also to an int!
    final int nBytesToRead = nRest >= nBufferLength ? nBufferLength : (int) nRest;
    if (nBytesToRead == 0)
      break;
    // Potentially blocking read
    final int nBytesRead = aIS.read (aBuffer, 0, nBytesToRead);
    if (nBytesRead == -1)
    {
      // EOF
      break;
    }
    if (nBytesRead > 0)
    {
      // At least one byte read
      aOS.write (aBuffer, 0, nBytesRead);
      nTotalBytesWritten += nBytesRead;
      nRest -= nBytesRead;
    }
  }
  return nTotalBytesWritten;
}
 
Example #20
Source File: AbstractXMLSerializer.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
/**
 * Write the specified node to the specified {@link Writer}.
 *
 * @param aNode
 *        The node to write. May not be <code>null</code>.
 * @param aWriter
 *        The writer to serialize onto. May not be <code>null</code>.
 */
public final void write (@Nonnull final NODETYPE aNode, @Nonnull @WillNotClose final Writer aWriter)
{
  final XMLEmitter aXMLWriter = createXMLEmitter (aWriter, m_aSettings);
  // No parent node
  // No previous and no next sibling
  emitNode (aXMLWriter, null, null, aNode, null);
  // Flush is important for Writer!
  StreamHelper.flush (aWriter);
}
 
Example #21
Source File: XMLEmitter.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
public XMLEmitter (@Nonnull @WillNotClose final Writer aWriter, @Nonnull final IXMLWriterSettings aSettings)
{
  m_aWriter = ValueEnforcer.notNull (aWriter, "Writer");
  m_aXMLWriterSettings = ValueEnforcer.notNull (aSettings, "Settings");
  m_eXMLVersion = aSettings.getSerializeVersion ();
  m_cAttrValueBoundary = aSettings.isUseDoubleQuotesForAttributes () ? '"' : '\'';
  m_eAttrValueCharMode = aSettings.isUseDoubleQuotesForAttributes () ? EXMLCharMode.ATTRIBUTE_VALUE_DOUBLE_QUOTES
                                                                     : EXMLCharMode.ATTRIBUTE_VALUE_SINGLE_QUOTES;
  m_bOrderAttributesAndNamespaces = aSettings.isOrderAttributesAndNamespaces ();
}
 
Example #22
Source File: StreamHelper.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
private static void _readUntilEOF (@Nonnull @WillNotClose final InputStream aIS,
                                   @Nonnull final byte [] aBuffer,
                                   @Nonnull final ObjIntConsumer <? super byte []> aConsumer) throws IOException
{
  ValueEnforcer.notNull (aIS, "InputStream");
  ValueEnforcer.notNull (aBuffer, "Buffer");
  ValueEnforcer.notNull (aConsumer, "Consumer");

  int nBytesRead;
  // Potentially blocking read
  while ((nBytesRead = aIS.read (aBuffer, 0, aBuffer.length)) > -1)
    aConsumer.accept (aBuffer, nBytesRead);
}
 
Example #23
Source File: JsonValueSerializerTypeConverterToString.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
public void appendAsJsonString (@Nullable final Object aValue,
                                @Nonnull @WillNotClose final Writer aWriter) throws IOException
{
  ValueEnforcer.notNull (aWriter, "Writer");

  final String sValue = TypeConverter.convert (aValue, String.class);
  aWriter.write (sValue);
}
 
Example #24
Source File: JsonWriter.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
public void writeToWriter (@Nonnull final IJson aJson, @Nonnull @WillNotClose final Writer aWriter) throws IOException
{
  ValueEnforcer.notNull (aJson, "Json");
  ValueEnforcer.notNull (aWriter, "Writer");

  _writeToWriter (aJson, aWriter, 0);

  if (m_aSettings.isWriteNewlineAtEnd ())
    aWriter.write (m_aSettings.getNewlineString ());

  aWriter.flush ();
}
 
Example #25
Source File: RFC2616Codec.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
public void decode (@Nullable final char [] aEncodedBuffer,
                    @Nonnegative final int nOfs,
                    @Nonnegative final int nLen,
                    @Nonnull @WillNotClose final Writer aWriter)
{
  if (aEncodedBuffer == null)
    return;

  if (nLen < 2)
    throw new DecodeException ("At least the 2 quote characters must be present. Provided length is only " + nLen);

  if (aEncodedBuffer[nOfs] != QUOTE_CHAR)
    throw new DecodeException ("The provided bytes does not seem to be encoded. The first byte is not the double quote character.");
  final int nLastOfs = nOfs + nLen - 1;
  if (aEncodedBuffer[nLastOfs] != QUOTE_CHAR)
    throw new DecodeException ("The provided bytes does not seem to be encoded. The last byte is not the double quote character.");

  try
  {
    for (int i = nOfs + 1; i < nLastOfs; ++i)
    {
      final char c = aEncodedBuffer[i];
      if (c == ESCAPE_CHAR)
      {
        if (i == nLastOfs - 1)
          throw new DecodeException ("The encoded string seems to be cut. The second last character cannot be an escape character.");
        ++i;
        aWriter.write (aEncodedBuffer[i]);
      }
      else
        aWriter.write (c);
    }
  }
  catch (final IOException ex)
  {
    throw new DecodeException ("Failed to decode RFC2616", ex);
  }
}
 
Example #26
Source File: URLCodec.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
public void decode (@Nullable final byte [] aEncodedBuffer,
                    @Nonnegative final int nOfs,
                    @Nonnegative final int nLen,
                    @Nonnull @WillNotClose final OutputStream aOS)
{
  if (aEncodedBuffer == null || nLen == 0)
    return;

  try
  {
    for (int i = 0; i < nLen; i++)
    {
      final int b = aEncodedBuffer[nOfs + i];
      if (b == PLUS)
        aOS.write (SPACE);
      else
        if (b == ESCAPE_CHAR)
        {
          if (i >= nLen - 2)
            throw new DecodeException ("Invalid URL encoding. Premature end of input after escape char");
          final char cHigh = (char) aEncodedBuffer[nOfs + i + 1];
          final char cLow = (char) aEncodedBuffer[nOfs + i + 2];
          i += 2;
          final int nDecodedValue = StringHelper.getHexByte (cHigh, cLow);
          if (nDecodedValue < 0)
            throw new DecodeException ("Invalid URL encoding for " + (int) cHigh + " and " + (int) cLow);

          aOS.write (nDecodedValue);
        }
        else
        {
          aOS.write (b);
        }
    }
  }
  catch (final IOException ex)
  {
    throw new DecodeException ("Failed to decode URL", ex);
  }
}
 
Example #27
Source File: NonBlockingProperties.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
private void _store (@Nonnull @WillNotClose final Writer aWriter,
                     @Nullable final String sComments,
                     final boolean bEscapeUnicode) throws IOException
{
  if (sComments != null)
    _writeComments (aWriter, sComments);

  final String sNewLine = ENewLineMode.DEFAULT.getText ();
  aWriter.write ("#" + ZonedDateTime.now ().toString () + sNewLine);

  for (final Map.Entry <String, String> aEntry : entrySet ())
  {
    String sKey = aEntry.getKey ();
    sKey = _saveConvert (sKey, true, bEscapeUnicode);

    String sValue = aEntry.getValue ();
    /*
     * No need to escape embedded and trailing spaces for value, hence pass
     * false to flag.
     */
    sValue = sValue == null ? "" : _saveConvert (sValue, false, bEscapeUnicode);

    aWriter.write (sKey);
    aWriter.write ('=');
    aWriter.write (sValue);
    aWriter.write (sNewLine);
  }
  aWriter.flush ();
}
 
Example #28
Source File: LZWCodec.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
public void decode (@Nullable final byte [] aEncodedBuffer,
                    @Nonnegative final int nOfs,
                    @Nonnegative final int nLen,
                    @Nonnull @WillNotClose final OutputStream aOS)
{
  if (aEncodedBuffer == null)
    return;

  try (final NonBlockingByteArrayInputStream aIS = new NonBlockingByteArrayInputStream (aEncodedBuffer, nOfs, nLen))
  {
    decode (aIS, aOS);
  }
}
 
Example #29
Source File: IdentityByteArrayCodec.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
public void encode (@Nullable final byte [] aDecodedBuffer,
                    @Nonnegative final int nOfs,
                    @Nonnegative final int nLen,
                    @Nonnull @WillNotClose final OutputStream aOS)
{
  try
  {
    aOS.write (aDecodedBuffer, nOfs, nLen);
  }
  catch (final IOException ex)
  {
    throw new IllegalStateException (ex);
  }
}
 
Example #30
Source File: QuotedPrintableCodec.java    From ph-commons with Apache License 2.0 5 votes vote down vote up
public void decode (@Nullable final byte [] aEncodedBuffer,
                    @Nonnegative final int nOfs,
                    @Nonnegative final int nLen,
                    @Nonnull @WillNotClose final OutputStream aOS)
{
  if (aEncodedBuffer == null || nLen == 0)
    return;

  try
  {
    for (int i = 0; i < nLen; i++)
    {
      final int b = aEncodedBuffer[nOfs + i];
      if (b == ESCAPE_CHAR)
      {
        if (i >= nLen - 2)
          throw new DecodeException ("Invalid quoted-printable encoding. Premature end of input after escape char");
        final char cHigh = (char) aEncodedBuffer[nOfs + i + 1];
        final char cLow = (char) aEncodedBuffer[nOfs + i + 2];
        i += 2;
        final int nDecodedValue = StringHelper.getHexByte (cHigh, cLow);
        if (nDecodedValue < 0)
          throw new DecodeException ("Invalid quoted-printable encoding for " + (int) cHigh + " and " + (int) cLow);

        aOS.write (nDecodedValue);
      }
      else
      {
        aOS.write (b);
      }
    }
  }
  catch (final IOException ex)
  {
    throw new DecodeException ("Failed to decode quoted-printable", ex);
  }
}