MD5InputStream.java
上传用户:demmber
上传日期:2007-12-22
资源大小:717k
文件大小:4k
源码类别:

Java编程

开发平台:

Java

  1. /*
  2.  * @(#)MD5InputStream.java 0.3-3 06/05/2001
  3.  *
  4.  *  This file is part of the HTTPClient package
  5.  *  Copyright (C) 1996-2001 Ronald Tschal鋜
  6.  *
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Lesser General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Lesser General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU Lesser General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20.  *  MA 02111-1307, USA
  21.  *
  22.  *  For questions, suggestions, bug-reports, enhancement-requests etc.
  23.  *  I may be contacted at:
  24.  *
  25.  *  ronald@innovation.ch
  26.  *
  27.  *  The HTTPClient's home page is located at:
  28.  *
  29.  *  http://www.innovation.ch/java/HTTPClient/ 
  30.  *
  31.  */
  32. package HTTPClient;
  33. import java.io.IOException;
  34. import java.io.InputStream;
  35. import java.io.FilterInputStream;
  36. import java.security.MessageDigest;
  37. import java.security.NoSuchAlgorithmException;
  38. /**
  39.  * This class calculates a running md5 digest of the data read. When the
  40.  * stream is closed the calculated digest is passed to a HashVerifier which
  41.  * is expected to verify this digest and to throw an Exception if it fails.
  42.  *
  43.  * @version 0.3-3  06/05/2001
  44.  * @author Ronald Tschal鋜
  45.  */
  46. class MD5InputStream extends FilterInputStream
  47. {
  48.     private HashVerifier verifier;
  49.     private MessageDigest md5;
  50.     private long rcvd = 0;
  51.     private boolean closed = false;
  52.     /**
  53.      * @param is the input stream over which the md5 hash is to be calculated
  54.      * @param verifier the HashVerifier to invoke when the stream is closed
  55.      */
  56.     public MD5InputStream(InputStream is, HashVerifier verifier)
  57.     {
  58. super(is);
  59. this.verifier = verifier;
  60. try
  61.     { md5 = MessageDigest.getInstance("MD5"); }
  62. catch (NoSuchAlgorithmException nsae)
  63.     { throw new Error(nsae.toString()); }
  64.     }
  65.     public synchronized int read() throws IOException
  66.     {
  67. int b = in.read();
  68. if (b != -1)
  69.     md5.update((byte) b);
  70. else
  71.     real_close();
  72. rcvd++;
  73. return b;
  74.     }
  75.     public synchronized int read(byte[] buf, int off, int len)
  76.     throws IOException
  77.     {
  78. int num = in.read(buf, off, len);
  79. if (num > 0)
  80.     md5.update(buf, off, num);
  81. else
  82.     real_close();
  83. rcvd += num;
  84. return num;
  85.     }
  86.     public synchronized long skip(long num)  throws IOException
  87.     {
  88. byte[] tmp = new byte[(int) num];
  89. int got = read(tmp, 0, (int) num);
  90. if (got > 0)
  91.     return (long) got;
  92. else
  93.     return 0L;
  94.     }
  95.     /**
  96.      * Close the stream and check the digest. If the stream has not been
  97.      * fully read then the rest of the data will first be read (and discarded)
  98.      * to complete the digest calculation.
  99.      *
  100.      * @exception IOException if the close()'ing the underlying stream throws
  101.      *                        an IOException, or if the expected digest and
  102.      *                        the calculated digest don't match.
  103.      */
  104.     public synchronized void close()  throws IOException
  105.     {
  106. while (skip(10000) > 0) ;
  107. real_close();
  108.     }
  109.     /**
  110.      * Close the stream and check the digest.
  111.      *
  112.      * @exception IOException if the close()'ing the underlying stream throws
  113.      *                        an IOException, or if the expected digest and
  114.      *                        the calculated digest don't match.
  115.      */
  116.     private void real_close()  throws IOException
  117.     {
  118. if (closed)  return;
  119. closed = true;
  120. in.close();
  121. verifier.verifyHash(md5.digest(), rcvd);
  122.     }
  123. }