Program: 89712
Project: 89712
Buggy source:
/** 
 * An implementation of the getInputStream operation that works with FTP. Notice that most of the special work (logging out and checking MD5) happens in the close() method of the returned InputStream, since that is the only place where we can know we're done.
 * @return An InputStream that will deliver the data transferred by FTP.Holding on to this for long periods without reading any data might cause a timeout.
 */
public InputStream getInputStream(){
  if (filesize == 0) {
    return new ByteArrayInputStream(new byte[]{});
  }
  try {
    logOn();
    InputStream in=currentFTPClient.retrieveFileStream(ftpFileName);
    if (in == null) {
      throw new IOFailure("String_Node_Str" + getFtpErrorMessage());
    }
    if (useChecksums) {
      in=new DigestInputStream(in,MD5.getMessageDigestInstance());
    }
    return new FilterInputStream(in){
      public void close() throws IOException {
        try {
          super.close();
          if (useChecksums) {
            String newChecksum=MD5.toHex(((DigestInputStream)in).getMessageDigest().digest());
            if (!newChecksum.equals(checksum)) {
              final String msg="String_Node_Str" + ftpFileName + "String_Node_Str"+ checksum+ "String_Node_Str"+ newChecksum;
              log.warn(msg);
              throw new IOFailure(msg);
            }
          }
        }
  finally {
          logOut();
          if (!multipleDownloads) {
            cleanup();
          }
        }
      }
    }
;
  }
 catch (  IOException e) {
    final String msg="String_Node_Str" + ftpFileName + "String_Node_Str";
    log.warn(msg,e);
    throw new IOFailure(msg,e);
  }
}

Fixed version (ground truth):
/** 
 * An implementation of the getInputStream operation that works with FTP. Notice that most of the special work (logging out and checking MD5) happens in the close() method of the returned InputStream, since that is the only place where we can know we're done.
 * @return An InputStream that will deliver the data transferred by FTP.Holding on to this for long periods without reading any data might cause a timeout.
 */
public InputStream getInputStream(){
  if (filesize == 0) {
    return new ByteArrayInputStream(new byte[]{});
  }
  try {
    logOn();
    InputStream in=currentFTPClient.retrieveFileStream(ftpFileName);
    if (in == null) {
      throw new IOFailure("String_Node_Str" + getFtpErrorMessage());
    }
    if (useChecksums) {
      in=new DigestInputStream(in,MD5.getMessageDigestInstance());
    }
    return new FilterInputStream(in){
      public void close() throws IOException {
        try {
          super.close();
          if (useChecksums) {
            String newChecksum=MD5.toHex(((DigestInputStream)in).getMessageDigest().digest());
            if (!newChecksum.equals(checksum)) {
              final String msg="String_Node_Str" + ftpFileName + "String_Node_Str"+ checksum+ "String_Node_Str"+ newChecksum;
              log.warn(msg);
              throw new IOFailure(msg);
            }
          }
        }
  finally {
          logOut();
          if (!multipleDownloads) {
            cleanup();
          }
        }
      }
    }
;
  }
 catch (  IOException e) {
    String msg="String_Node_Str" + ftpFileName + "String_Node_Str";
    if (e instanceof CopyStreamException) {
      CopyStreamException realException=(CopyStreamException)e;
      msg+="String_Node_Str" + realException.getIOException() + "String_Node_Str";
    }
    log.warn(msg,e);
    throw new IOFailure(msg,e);
  }
}