⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 totorrentimpl.java

📁 这是一个基于java编写的torrent的P2P源码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * File    : TOTorrentImpl.java
 * Created : 5 Oct. 2003
 * By      : Parg 
 * 
 * Azureus - a Java Bittorrent client
 *
 * 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.
 *
 * 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 ( see the LICENSE file ).
 *
 * 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
 */

package org.gudy.azureus2.core3.torrent.impl;


import java.io.*;
import java.net.*;
import java.util.*;

import org.gudy.azureus2.core3.logging.LogRelation;
import org.gudy.azureus2.core3.torrent.*;
import org.gudy.azureus2.core3.util.*;

import com.aelitis.azureus.core.AzureusCoreFactory;

public class 
TOTorrentImpl
	extends LogRelation
	implements TOTorrent
{
	protected static final String TK_ANNOUNCE			= "announce";
	protected static final String TK_ANNOUNCE_LIST		= "announce-list";
	protected static final String TK_COMMENT			= "comment";
	protected static final String TK_CREATION_DATE		= "creation date";
	protected static final String TK_CREATED_BY			= "created by";
	
	protected static final String TK_INFO				= "info";
	protected static final String TK_NAME				= "name";
	protected static final String TK_LENGTH				= "length";
	protected static final String TK_PATH				= "path";
	protected static final String TK_FILES				= "files";
	protected static final String TK_PIECE_LENGTH		= "piece length";
	protected static final String TK_PIECES				= "pieces";
		
	protected static final String TK_PRIVATE			= "private";

	protected static final String TK_NAME_UTF8			= "name.utf-8";
	protected static final String TK_PATH_UTF8			= "path.utf-8";
	protected static final String TK_COMMENT_UTF8		= "comment.utf-8";
	
	protected static final List	TK_ADDITIONAL_OK_ATTRS = 
		Arrays.asList(new String[]{TK_COMMENT_UTF8, AZUREUS_PROPERTIES });
	
	private byte[]							torrent_name;
	private byte[]							torrent_name_utf8;
	
	private byte[]							comment;
	private URL								announce_url;
	private TOTorrentAnnounceURLGroupImpl	announce_group = new TOTorrentAnnounceURLGroupImpl(this);
	
	private long		piece_length;
	private byte[][]	pieces;
	private int			number_of_pieces;
	
	private byte[]		torrent_hash;
	private HashWrapper	torrent_hash_wrapper;
	
	private boolean				simple_torrent;
	private TOTorrentFileImpl[]	files;

	private long				creation_date;
	private byte[]				created_by;
	
	private Map					additional_properties 		= new HashMap();
	private Map					additional_info_properties	= new HashMap();
	
	private boolean				created;
	private boolean				serialising;
	
	protected AEMonitor this_mon 	= new AEMonitor( "TOTorrent" );

	/** 
	 * Constructor for deserialisation
	 */
	
	protected
	TOTorrentImpl()
	{
	}

	/** 
	 * Constructor for creation
	 */
	
	protected
	TOTorrentImpl(
		String		_torrent_name,
		URL			_announce_url,
		boolean		_simple_torrent )
		
		throws TOTorrentException
	{
		created	= true;
		
		try{
		
			torrent_name		= _torrent_name.getBytes( Constants.DEFAULT_ENCODING );
			
			torrent_name_utf8	= torrent_name;
			
			setAnnounceURL( _announce_url );
			
			simple_torrent		= _simple_torrent;
			
		}catch( UnsupportedEncodingException e ){
			
			throw( new TOTorrentException( 	"Unsupported encoding for '" + _torrent_name + "'",
											TOTorrentException.RT_UNSUPPORTED_ENCODING));
		}
	}
	
	public void
	serialiseToBEncodedFile(
		final File		output_file )
	
		throws TOTorrentException
	{	
			// we have to defer marking as created until some kind of persisting occurs as we don't know that the info-hash is "permanent" until#
			// this point (external code can set info-hash internal properties between create + complete )
		
		if ( created ){
			
			TorrentUtils.addCreatedTorrent( this );
		}
		
		byte[]	res = serialiseToByteArray();
						
        BufferedOutputStream bos = null;
						
		try{
			File parent = output_file.getParentFile();
			if (parent == null) {
				throw new TOTorrentException( "Path '" + output_file + "' is invalid", TOTorrentException.RT_WRITE_FAILS);
			}
			
			// We would expect this to be normally true most of the time.
			if (!parent.isDirectory()) {
				
				// Try to create a directory.
				boolean dir_created = FileUtil.mkdirs(parent);
				
				// Something strange going on...
				if (!dir_created) {
					
					// Does it exist already?
					if (parent.exists()) {
						
						// And it really isn't a directory?
						if (!parent.isDirectory()) {
							
							// How strange.
							throw new TOTorrentException( "Path '" + output_file + "' is invalid", TOTorrentException.RT_WRITE_FAILS);
							
						}
						
						// It is a directory which does exist. But we tested for that earlier. Perhaps it has been created in the
						// meantime.
						else {
							/* do nothing */
						}
					}
					
					// It doesn't exist, and we couldn't create it.
					else {
						throw new TOTorrentException( "Failed to create directory '" + parent + "'", TOTorrentException.RT_WRITE_FAILS );
					}
				} // end if (!dir_created)
				
			} // end if (!parent.isDirectory)
			
			
			File temp = new File( parent, output_file.getName() + ".saving");
            
			if ( temp.exists()){
				
				if ( !temp.delete()){
					
					throw( new TOTorrentException( "Insufficient permissions to delete '" + temp + "'", TOTorrentException.RT_WRITE_FAILS ));
				}
			}else{
				
				boolean	ok = false;
				
				try{
					ok = temp.createNewFile();
					
				}catch( Throwable e ){
				}
				
				if ( !ok ){
					
					throw( new TOTorrentException( "Insufficient permissions to write '" + temp + "'", TOTorrentException.RT_WRITE_FAILS ));

				}
			}
			
            FileOutputStream fos = new FileOutputStream( temp, false );
			
            bos = new BufferedOutputStream( fos, 8192 );
			
            bos.write( res );
			
            bos.flush();
			
            fos.getFD().sync();
            
            bos.close();
            
            bos = null;
              
              //only use newly saved file if it got this far, i.e. it was written successfully
            
            if ( temp.length() > 1L ) {
            	output_file.delete(); // Will fail silently if it doesn't exist.
                temp.renameTo( output_file );
            }
             	
		}catch( TOTorrentException e ){
			
			throw( e );
			
		}catch( Throwable e){
							
			throw( new TOTorrentException( 	"Failed to serialise torrent: " + Debug.getNestedExceptionMessage(e),
											TOTorrentException.RT_WRITE_FAILS ));
							
		}finally{
							
			if ( bos != null ){
				
				try{
					bos.close();
					
				}catch( IOException e ){
				
					Debug.printStackTrace( e );
				}
			}
		}
	}
	
	protected byte[]
	serialiseToByteArray()
	
		throws TOTorrentException
	{
		if ( created ){
			
			TorrentUtils.addCreatedTorrent( this );
		}
		
		Map	root = serialiseToMap();
			
		try{
			return( BEncoder.encode( root ));
			
		}catch( IOException e ){

			throw( 	new TOTorrentException( 	
							"Failed to serialise torrent: " + Debug.getNestedExceptionMessage(e),
							TOTorrentException.RT_WRITE_FAILS ));
			
		}
	}		

	public Map
	serialiseToMap()
	
		throws TOTorrentException
	{		
			// protect against recursion when getting the hash 
		
		if ( created && !serialising ){
			
			try{
				serialising	= true;	// not thread safe but we can live without the hassle of using TLS or whatever
					
				TorrentUtils.addCreatedTorrent( this );
				
			}finally{
				
				serialising = false;
			}
		}
		
		Map	root = new HashMap();
		
		writeStringToMetaData( root, TK_ANNOUNCE, announce_url.toString());
		
		TOTorrentAnnounceURLSet[] sets = announce_group.getAnnounceURLSets();
		
		if (sets.length > 0 ){
			
			List	announce_list = new ArrayList();
			
			for (int i=0;i<sets.length;i++){
				
				TOTorrentAnnounceURLSet	set = sets[i];
				
				URL[]	urls = set.getAnnounceURLs();
				
				if ( urls.length == 0 ){
					
					continue;
				}
				
				List sub_list = new ArrayList();
				
				announce_list.add( sub_list );
				
				for (int j=0;j<urls.length;j++){
					
					sub_list.add( writeStringToMetaData( urls[j].toString())); 
				}
			}
			
			if ( announce_list.size() > 0 ){
				
				root.put( TK_ANNOUNCE_LIST, announce_list );
			}
		}
		
		if ( comment != null ){
			
			root.put( TK_COMMENT, comment );			
		}
		
		if ( creation_date != 0 ){
			
			root.put( TK_CREATION_DATE, new Long( creation_date ));
		}
		
		if ( created_by != null ){
			
			root.put( TK_CREATED_BY, created_by );						
		}
		
		Map info = new HashMap();
		
		root.put( TK_INFO, info );
		
		info.put( TK_PIECE_LENGTH, new Long( piece_length ));
		
		if ( pieces == null ){
			
			throw( new TOTorrentException( "Pieces is null", TOTorrentException.RT_WRITE_FAILS ));
		}
		
		byte[]	flat_pieces = new byte[pieces.length*20];
		
		for (int i=0;i<pieces.length;i++){
			
			System.arraycopy( pieces[i], 0, flat_pieces, i*20, 20 );
		}
		
		info.put( TK_PIECES, flat_pieces );
		
		info.put( TK_NAME, torrent_name );
		
		if ( torrent_name_utf8 != null ){
			
			info.put( TK_NAME_UTF8, torrent_name_utf8 );
		}
		
		if ( simple_torrent ){
		
			TOTorrentFile	file = files[0];
			
			info.put( TK_LENGTH, new Long( file.getLength()));
			
		}else{
	
			List	meta_files = new ArrayList();
		
			info.put( TK_FILES, meta_files );
		
			for (int i=0;i<files.length;i++){
				
				TOTorrentFileImpl	file	= files[i];
				
				Map	file_map = new HashMap();
		
				meta_files.add( file_map );
				
				file_map.put( TK_LENGTH, new Long( file.getLength()));
				
				List path = new ArrayList();
				
				file_map.put( TK_PATH, path );
				
				byte[][]	path_comps = file.getPathComponents();
				
				for (int j=0;j<path_comps.length;j++){
					
					path.add( path_comps[j]);
				}
				
				if ( file.isUTF8()){
					
					List utf8_path = new ArrayList();
					
					file_map.put( TK_PATH_UTF8, utf8_path );
										
					for (int j=0;j<path_comps.length;j++){
						
						utf8_path.add( path_comps[j]);
					}
				}
				
				Map file_additional_properties = file.getAdditionalProperties();
				
				Iterator prop_it = file_additional_properties.keySet().iterator();
				
				while( prop_it.hasNext()){
					
					String	key = (String)prop_it.next();
					
					file_map.put( key, file_additional_properties.get( key ));
				}
			}
		}
		
		Iterator info_it = additional_info_properties.keySet().iterator();
		
		while( info_it.hasNext()){
		
			String	key = (String)info_it.next();
			
			info.put( key, additional_info_properties.get( key ));	
		}
		
		Iterator it = additional_properties.keySet().iterator();
		
		while( it.hasNext()){
			
			String	key = (String)it.next();
			
			Object	value = additional_properties.get( key );
			
			if ( value != null ){
				
				root.put( key, value );
			}
		}
		
		return( root );
	}
	
	public void
	serialiseToXMLFile(
	  File		file )
		  
	  throws TOTorrentException
	{
		if ( created ){
			
			TorrentUtils.addCreatedTorrent( this );
		}
		
		TOTorrentXMLSerialiser	serialiser = new TOTorrentXMLSerialiser( this );
		
		serialiser.serialiseToFile( file );
	}
	
	public byte[]
	getName()
	{
		return( torrent_name );
	}
	
	protected void
	setName(
		byte[]	_name )
	{
		torrent_name	= _name;
	}
	
	public boolean
	isSimpleTorrent()
	{
		return( simple_torrent );
	}
	
	public byte[]
	getComment()
	{
		return( comment );
	}
	
	protected void
	setComment(
		byte[]		_comment )
	
	{
		comment = _comment;
	}
	
	public void
	setComment(
		String	_comment )
	{
		try{
		
			byte[]	utf8_comment = _comment.getBytes( Constants.DEFAULT_ENCODING );
			
			setComment( utf8_comment );
			
			setAdditionalByteArrayProperty( TK_COMMENT_UTF8, utf8_comment );
			
		}catch( UnsupportedEncodingException e ){
			
			Debug.printStackTrace( e );
			
			comment = null;
		}
	}
		
	public URL
	getAnnounceURL()
	{
		return( announce_url );
	}
	
	public boolean
	setAnnounceURL(
		URL		url )
	{
		URL newURL = anonymityTransform( url );
		String s0 = (newURL == null) ? "" : newURL.toString();
		String s1 = (announce_url == null) ? "" : announce_url.toString();
		if (s0.equals(s1))
			return false;
		
		announce_url	= newURL;
		return true;
	}

	public long
	getCreationDate()
	{
		return( creation_date );
	}
	
	public void
	setCreationDate(
		long		_creation_date )
	{
		creation_date 	= _creation_date;
	}
	
	protected void
	setCreatedBy(
		byte[]		_created_by )
	{
		created_by	= _created_by;
	}
	
	protected void
	setCreatedBy(
		String		_created_by )
	{
		try{
		
			setCreatedBy( _created_by.getBytes( Constants.DEFAULT_ENCODING ));
			
		}catch( UnsupportedEncodingException e ){
			
			Debug.printStackTrace( e );
			
			created_by = null;
		}	
	}
	
	public byte[]
	getCreatedBy()
	{
		return( created_by );
	}
	
	public boolean
	isCreated()
	{
		return( created );
	}
	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -