package client.shareserver;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import common.FS2Constants;
import common.ProgressTracker;
import common.Util;

/**
 * Provides java with the ability to produce digests of files but at a throttled rate.
 * Provide null for the bandwidth sharer and then it will not throttle the digestion.
 * 
 * It will also append the extra bytes to the end of the file bytes before digesting.
 * This can be used as an additional seed.
 * 
 * This is usefull if a lot of files require digesting and the computer should not be monopolised.
 * (IONice and Nice should probably be used in preference to a stringent throttle though)
 * @author gary
 *
 */
public class ThrottledFileDigester {

	public static String digest(InputStream inStream, BandwidthSharer bs, String algorithm, byte[] extra, ProgressTracker tracker) throws NoSuchAlgorithmException, IOException {
		DigestInputStream md5er = null;
		try {
			if (bs != null) {
				md5er = new DigestInputStream(new ThrottledInputStream(inStream,bs),MessageDigest.getInstance(algorithm));
			} else {
				md5er = new DigestInputStream(inStream,MessageDigest.getInstance(algorithm));
			}
			byte[] buf = new byte[FS2Constants.ARBITRARY_BUFFER_SIZE];
			int read=0;
			while ((read=md5er.read(buf)) > 0) {
				if (tracker!=null) tracker.progress(read);
			}
			String retStr = Util.bytesToHexString(md5er.getMessageDigest().digest(extra));
			return retStr;
		} finally {
			if (md5er != null) md5er.close();
		}
	}

	/**
	 * Generates and returns the fs2 digest of a file.
	 * @param inFile
	 * @param bs The bandwidth sharer to throttle the digesting. Use null for unlimited.
	 * @return the fs2 digest of the file as a string
	 * @throws IOException 
	 * @throws FileNotFoundException 
	 * @throws NoSuchAlgorithmException 
	 */
	public static String fs2DigestFile(File file, BandwidthSharer bs) throws NoSuchAlgorithmException, IOException {
		return ThrottledFileDigester.digest(new FileCropperStream(file, FS2Constants.FILE_DIGEST_HEAD_FOOT_LENGTH), bs, FS2Constants.FILE_DIGEST_ALGORITHM, Long.toString(file.length()).getBytes("UTF-8"), null);
	}
	
	public static String fs2TrackableDigestFile(File file, ProgressTracker tracker) throws NoSuchAlgorithmException, IOException {
		return ThrottledFileDigester.digest(new FileCropperStream(file, FS2Constants.FILE_DIGEST_HEAD_FOOT_LENGTH), null, FS2Constants.FILE_DIGEST_ALGORITHM, Long.toString(file.length()).getBytes("UTF-8"), tracker);
	}
}

@@ -47,46 +47,8 @@
 le;%0A
-import java.io.FileNotFoundException;%0A
 impo
@@ -319,17 +319,17 @@
 rovides 
-j
+J
 ava with
@@ -418,25 +418,25 @@
 for the 
-b
+B
 andwidth
  sharer 
@@ -423,26 +423,25 @@
 he Bandwidth
- s
+S
 harer and th
@@ -633,17 +633,16 @@
 s useful
-l
  if a lo
@@ -824,11 +824,8 @@
 ary%0A
- *%0A
  */%0A
@@ -905,22 +905,19 @@
 tream in
-Stream
+put
 , Bandwi
@@ -1040,199 +1040,100 @@
 %7B%0A%09%09
-DigestInputStream md5er = null;%0A%09%09try %7B%0A%09%09%09if (bs != null) %7B%0A%09%09%09%09md5er = new DigestInputStream(new ThrottledInputStream(inStream,bs),MessageDigest.getInstance(algorithm));%0A%09%09%09%7D else %7B%0A%09%09%09%09md5
+if (bs != null) input = new ThrottledInputStream(input, bs);%0A%09%09try (DigestInputStream digest
 er =
@@ -1161,15 +1161,13 @@
 m(in
-Stream,
+put, 
 Mess
@@ -1199,22 +1199,19 @@
 orithm))
-;%0A%09%09%09%7D
+) %7B
 %0A%09%09%09byte
@@ -1276,17 +1276,19 @@
 int read
-=
+ = 
 0;%0A%09%09%09wh
@@ -1301,12 +1301,17 @@
 read
-=md5
+ = digest
 er.r
@@ -1342,18 +1342,20 @@
 (tracker
+ 
 !=
+ 
 null) tr
@@ -1388,23 +1388,14 @@
 %0A%09%09%09
-String retStr =
+return
  Uti
@@ -1413,19 +1413,22 @@
 xString(
-md5
+digest
 er.getMe
@@ -1461,77 +1461,8 @@
 ));%0A
-%09%09%09return retStr;%0A%09%09%7D finally %7B%0A%09%09%09if (md5er != null) md5er.close();%0A
 %09%09%7D%0A
@@ -1537,11 +1537,9 @@
 ram 
-inF
+f
 ile%0A
@@ -1560,17 +1560,17 @@
 The 
-b
+B
 andwidth
  sha
@@ -1565,18 +1565,17 @@
 andwidth
- s
+S
 harer to
@@ -1635,17 +1635,17 @@
 @return 
-t
+T
 he fs2 d
@@ -1673,16 +1673,17 @@
 a string
+.
 %0A%09 * @th
@@ -1704,43 +1704,8 @@
 on %0A
-%09 * @throws FileNotFoundException %0A
 %09 * 
@@ -1870,201 +1870,214 @@
 urn 
-ThrottledFileDigester.digest(new FileCropperStream(file, FS2Constants.FILE_DIGEST_HEAD_FOOT_LENGTH), bs, FS2Constants.FILE_DIGEST_ALGORITHM, Long.toString(file.length()).getBytes(%22UTF-8%22), null
+fs2DigestFile(file, bs, null);%0A%09%7D%0A%09%0A%09public static String fs2TrackableDigestFile(File file, ProgressTracker tracker) throws NoSuchAlgorithmException, IOException %7B%0A%09%09return fs2DigestFile(file, null, tracker
 );%0A%09
@@ -2101,33 +2101,24 @@
 c String fs2
-Trackable
 DigestFile(F
@@ -2118,32 +2118,52 @@
 tFile(File file,
+ BandwidthSharer bs,
  ProgressTracker
@@ -2232,30 +2232,8 @@
 urn 
-ThrottledFileDigester.
 dige
@@ -2307,20 +2307,18 @@
 ENGTH), 
-null
+bs
 , FS2Con

Modify file digester to remove some redundancy