/*
* Created on Oct 5, 2003
* Created by Paul Gardner
* Modified Apr 13, 2004 by Alon Rohter
* Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package org.gudy.azureus2.core3.torrent.impl;
import java.io.*;
import java.util.*;
import org.gudy.azureus2.core3.torrent.*;
import org.gudy.azureus2.core3.util.*;
public class
TOTorrentFileHasher
{
protected boolean do_other_per_file_hash;
protected int piece_length;
protected Vector pieces = new Vector();
protected byte[] buffer;
protected int buffer_pos;
protected SHA1Hasher overall_sha1_hash;
protected ED2KHasher overall_ed2k_hash;
protected byte[] sha1_digest;
protected byte[] ed2k_digest;
protected byte[] per_file_sha1_digest;
protected byte[] per_file_ed2k_digest;
protected TOTorrentFileHasherListener listener;
protected boolean cancelled;
protected
TOTorrentFileHasher(
boolean _do_other_overall_hashes,
boolean _do_other_per_file_hash,
int _piece_length,
TOTorrentFileHasherListener _listener )
{
if ( _do_other_overall_hashes ){
overall_sha1_hash = new SHA1Hasher();
overall_ed2k_hash = new ED2KHasher();
}
do_other_per_file_hash = _do_other_per_file_hash;
piece_length = _piece_length;
listener = _listener;
buffer = new byte[piece_length];
}
long
add(
File _file )
throws TOTorrentException
{
long file_length = 0;
InputStream is = null;
SHA1Hasher sha1_hash = null;
ED2KHasher ed2k_hash = null;
try{
if ( do_other_per_file_hash ){
sha1_hash = new SHA1Hasher();
ed2k_hash = new ED2KHasher();
}
is = new BufferedInputStream(new FileInputStream( _file ), 65536);
while(true){
if ( cancelled ){
throw( new TOTorrentException( "TOTorrentCreate: operation cancelled",
TOTorrentException.RT_CANCELLED ));
}
int len = is.read( buffer, buffer_pos, piece_length - buffer_pos );
if ( len > 0 ){
if ( do_other_per_file_hash ){
sha1_hash.update( buffer, buffer_pos, len );
ed2k_hash.update( buffer, buffer_pos, len );
}
file_length += len;
buffer_pos += len;
if ( buffer_pos == piece_length ){
// hash this piece
byte[] hash = new SHA1Hasher().calculateHash(buffer);
if ( overall_sha1_hash != null ){
overall_sha1_hash.update( buffer );
overall_ed2k_hash.update( buffer );
}
pieces.add( hash );
if ( listener != null ){
listener.pieceHashed( pieces.size() );
}
buffer_pos = 0;
}
}else{
break;
}
}
if ( do_other_per_file_hash ){
per_file_sha1_digest = sha1_hash.getDigest();
per_file_ed2k_digest = ed2k_hash.getDigest();
}
}catch( TOTorrentException e ){
throw( e );
}catch( Throwable e ){
throw( new TOTorrentException( "TOTorrentFileHasher: file read fails '" + e.toString() + "'",
TOTorrentException.RT_READ_FAILS ));
}finally {
if (is != null) {
try {
is.close();
}
catch (Exception e) {
}
}
}
return( file_length );
}
protected byte[]
getPerFileSHA1Digest()
{
return( per_file_sha1_digest );
}
protected byte[]
getPerFileED2KDigest()
{
return( per_file_ed2k_digest );
}
protected byte[][]
getPieces()
throws TOTorrentException
{
try{
if ( buffer_pos > 0 ){
byte[] rem = new byte[buffer_pos];
System.arraycopy( buffer, 0, rem, 0, buffer_pos );
pieces.addElement(new SHA1Hasher().calculateHash(rem));
if ( overall_sha1_hash != null ){
overall_sha1_hash.update( rem );
overall_ed2k_hash.update( rem );
}
if ( listener != null ){
listener.pieceHashed( pieces.size() );
}
buffer_pos = 0;
}
if ( overall_sha1_hash != null && sha1_digest == null ){
sha1_digest = overall_sha1_hash.getDigest();
ed2k_digest = overall_ed2k_hash.getDigest();
}
byte[][] res = new byte[pieces.size()][];
pieces.copyInto( res );
return( res );
}catch( Throwable e ){
throw( new TOTorrentException( "TOTorrentFileHasher: file read fails '" + e.toString() + "'",
TOTorrentException.RT_READ_FAILS ));
}
}
protected byte[]
getED2KDigest()
throws TOTorrentException
{
if ( ed2k_digest == null ){
getPieces();
}
return( ed2k_digest );
}
protected byte[]
getSHA1Digest()
throws TOTorrentException
{
if ( sha1_digest == null ){
getPieces();
}
return( sha1_digest );
}
protected void
cancel()
{
cancelled = true;
}
}