FileDocCategorySizeDatePackage
ResourceDownloaderTorrentImpl.javaAPI DocAzureus 3.0.3.412032Wed Jun 13 12:13:00 BST 2007org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader

ResourceDownloaderTorrentImpl

public class ResourceDownloaderTorrentImpl extends ResourceDownloaderBaseImpl implements ResourceDownloaderListener
author
parg

Fields Summary
public static final int
MAX_FOLLOWS
protected ResourceDownloaderBaseImpl
delegate
protected boolean
persistent
protected File
download_dir
protected long
size
protected org.gudy.azureus2.core3.torrent.TOTorrent[]
torrent_holder
protected DownloadManager
download_manager
protected Download
download
protected boolean
cancelled
protected ResourceDownloader
current_downloader
protected Object
result
protected AESemaphore
done_sem
Constructors Summary
public ResourceDownloaderTorrentImpl(ResourceDownloaderBaseImpl _parent, ResourceDownloader _delegate, boolean _persistent, File _download_dir)

			
	
	
			
					
								
								 
	
		super( _parent );
		
		persistent		= _persistent;
		download_dir	= _download_dir;
		delegate		= (ResourceDownloaderBaseImpl)_delegate;
		
		delegate.setParent( this );
		
		download_manager = PluginInitializer.getDefaultInterface().getDownloadManager();
	
Methods Summary
public voidasyncDownload()

		try{
			this_mon.enter();
		
			if ( cancelled ){
				
				done_sem.release();
				
				informFailed((ResourceDownloaderException)result);
				
			}else{
	
				if ( torrent_holder[0] == null ){
					
					current_downloader = delegate.getClone( this );
					
					informActivity( getLogIndent() + "Downloading: " + getName());
		
					current_downloader.addListener( this );
					
					current_downloader.asyncDownload();
					
				}else{
					
					downloadTorrent();
				}
			}
		}finally{
			
			this_mon.exit();
		}
	
public voidcancel()

		setCancelled();
		
		try{
			this_mon.enter();
		
			result	= new ResourceDownloaderException( "Download cancelled");
			
			cancelled	= true;
			
			informFailed((ResourceDownloaderException)result );
			
			done_sem.release();
			
			if ( current_downloader != null ){
				
				current_downloader.cancel();
			}
		}finally{
			
			this_mon.exit();
		}
	
public booleancompleted(ResourceDownloader downloader, java.io.InputStream data)

		try{			
			torrent_holder[0] = TOTorrentFactory.deserialiseFromBEncodedInputStream( data );
			
			if( torrent_holder[0].isSimpleTorrent()){
				
				downloadTorrent();
				
			}else{
				
				failed( this, new ResourceDownloaderException( "Only simple torrents supported" ));
			}
			
		}catch( TOTorrentException e ){
			
			failed( downloader, new ResourceDownloaderException( "Torrent deserialisation failed", e ));
			
		}finally{
			
			try{
				data.close();
				
			}catch( IOException e ){
			}
		}
		
		return( true );
	
public java.io.InputStreamdownload()

		asyncDownload();
		
		done_sem.reserve();
		
		if ( result instanceof InputStream ){
			
			return((InputStream)result);
		}
		
		throw((ResourceDownloaderException)result);
	
protected voiddownloadRemoved(java.io.File torrent_file, java.io.File data_dir)

		reportActivity( "Torrent removed" );

		if (!( result instanceof InputStream )){
			
			failed( this, new ResourceDownloaderException( "Download did not complete" ));
		}
	
protected voiddownloadSucceeded(Download download, java.io.File torrent_file, java.io.File data_dir)

		reportActivity("Torrent download complete");
		
		// assumption is that this is a SIMPLE torrent
		File target_file = 
			new File( data_dir,	new String(torrent_holder[0].getFiles()[0].getPathComponents()[0]));
					
			if ( !target_file.exists()){

				File	actual_target_file = new File(download.getSavePath());
				
				try{
					if ( download_dir != null && actual_target_file.exists()){
						
						FileUtil.copyFile( actual_target_file, target_file );
					}
					
				}catch( Throwable e ){
					
					Debug.printStackTrace(e);
				}
				
				target_file	= actual_target_file;
			}

		try{
			if ( !target_file.exists()){
				
				throw( new Exception( "File '" + target_file.toString() + "' not found" ));
			}
			
			InputStream	data = new FileInputStream( target_file );
			
			informComplete( data );
				
			result	= data;
				
			done_sem.release();
			
		}catch( Throwable e ){
			
			Debug.printStackTrace( e );
			
			failed( this, new ResourceDownloaderException( "Failed to read downloaded torrent data: " + e.getMessage(), e ));
		}
	
protected voiddownloadTorrent()

		try{
			informActivity( getLogIndent() + "Downloading: " + new String( torrent_holder[0].getName(), Constants.DEFAULT_ENCODING ));
			
				// we *don't* want this temporary file to be deleted automatically as we're
				// going to use it across Azureus restarts to hold the download data and
				// to seed it afterwards. Therefore we don't use AETemporaryFileHandler!!!!
			
			final File	torrent_file 	= File.createTempFile("AZU", null );
			
			if ( download_dir != null && !download_dir.exists()){
				
				FileUtil.mkdirs(download_dir);
			}
			
			final File	data_dir		= download_dir==null?torrent_file.getParentFile():download_dir;
			
			final TOTorrent	torrent = torrent_holder[0];
			
			TorrentUtils.setFlag( torrent, TorrentUtils.TORRENT_FLAG_LOW_NOISE, true );

			torrent.serialiseToBEncodedFile( torrent_file );
				
			if ( persistent ){
				
				download = download_manager.addDownload( new TorrentImpl(torrent), torrent_file, data_dir );
				
			}else{
				
				download = download_manager.addNonPersistentDownload( new TorrentImpl(torrent), torrent_file, data_dir );
			}
			
			download.moveTo(1);		
			
			download.setForceStart( true );
			
			// Prevents any move-on-completion or move-on-removal behaviour happening.
			download.setFlag(Download.FLAG_DISABLE_AUTO_FILE_MOVE, true);
			
			download_manager.addListener(
				new DownloadManagerListener()
				{
					public void
					downloadAdded(
						Download	download )
					{					
					}
					
					public void
					downloadRemoved(
						Download	_download )
					{
						if ( download == _download ){
							
							ResourceDownloaderTorrentImpl.this.downloadRemoved( torrent_file, data_dir );
						}
					}
				});
						
			download.addListener(
				new DownloadListener()
				{
					public void
					stateChanged(
						Download		download,
						int				old_state,
						int				new_state )
					{		
						// System.out.println( "state change:" + old_state + "->" + new_state );
						
						if ( new_state == Download.ST_SEEDING ){
							
							download.removeListener( this );
							
							downloadSucceeded( download, torrent_file, data_dir );
						}
					}

					public void
					positionChanged(
						Download	download, 
						int 		oldPosition,
						int 		newPosition )
					{
					}
				});
				
			Thread	t = 
				new AEThread( "RDTorrent percentage checker")
				{
					public void
					runSupport()
					{
						int	last_percentage = 0;
						
						while( result == null ){
														
							int	this_percentage = download.getStats().getCompleted()/10;
							
							long	total	= torrent.getSize();
														
							if ( this_percentage != last_percentage ){
								
								reportPercentComplete( ResourceDownloaderTorrentImpl.this, this_percentage );
							
								last_percentage = this_percentage;
							}
							
							try{
								Thread.sleep(1000);
								
							}catch( Throwable e ){
								
								Debug.printStackTrace( e );
							}
						}
					}
				};
				
			t.setDaemon( true );
			
			t.start();
			
				// its possible that the d/l has already occurred and it is seeding!
			
			if ( download.getState() == Download.ST_SEEDING ){
				
				downloadSucceeded( download, torrent_file, data_dir );
			}
		}catch( Throwable e ){
			
			failed( this, new ResourceDownloaderException( "Torrent download failed", e ));
		}
	
public voidfailed(ResourceDownloader downloader, ResourceDownloaderException e)

		result		= e;
		
		done_sem.release();

		informFailed(e);
	
public ResourceDownloaderBaseImplgetClone(ResourceDownloaderBaseImpl parent)

		ResourceDownloaderTorrentImpl c = new ResourceDownloaderTorrentImpl( parent, delegate.getClone( this ), persistent, download_dir );
		
		c.setSizeAndTorrent( size, torrent_holder );
		
		c.setProperties( this );

		return( c );
	
public java.lang.StringgetName()

		return( delegate.getName() + ": torrent" );
	
public longgetSize()

	
		if ( size == -2 ){
			
			try{
				size = getSizeSupport();
				
			}finally{
				
				if ( size == -2 ){
					
					size = -1;
				}
				
				setSize( size );
			}
		}
		

		return( size );
	
protected longgetSizeSupport()

		try{
			if ( torrent_holder[0] == null ){
				
				ResourceDownloader	x = delegate.getClone( this );
			
				addReportListener( x );
			
				InputStream	is = x.download();
				
				try{
					torrent_holder[0] = TOTorrentFactory.deserialiseFromBEncodedInputStream( is );
					
				}finally{
					
					try{
						is.close();
						
					}catch( IOException e ){
					}
				}
				
				if( !torrent_holder[0].isSimpleTorrent()){
					
					throw( new ResourceDownloaderException( "Only simple torrents supported" ));
				}
			}
			
			try{
				String	file_str = new String( torrent_holder[0].getName());
				
				int	pos = file_str.lastIndexOf( "." );
				
				String	file_type;
				
				if ( pos != -1 ){
				
					file_type = file_str.substring(pos+1);
					
				}else{
					
					file_type = null;
				}
				
				setProperty( 	ResourceDownloader.PR_STRING_CONTENT_TYPE,
								HTTPUtils.guessContentTypeFromFileType( file_type ));
				
			}catch( Throwable e ){
				
				Debug.printStackTrace(e);
			}
			
			return( torrent_holder[0].getSize());
			
		}catch( TOTorrentException e ){
			
			throw( new ResourceDownloaderException( "Torrent deserialisation failed", e ));
		}
	
public voidreportPercentComplete(ResourceDownloader downloader, int percentage)

		if ( downloader == this ){
			
			informPercentDone( percentage );
		}
	
protected voidsetProperty(java.lang.String name, java.lang.Object value)

		setPropertySupport( name, value );
		
		delegate.setProperty( name, value );
	
protected voidsetSize(long l)

		size	= l;
		
		if ( size >= 0 ){
			
			delegate.setSize( size );
		}
	
protected voidsetSizeAndTorrent(long _size, org.gudy.azureus2.core3.torrent.TOTorrent[] _torrent_holder)

		size			= _size;
		torrent_holder	= _torrent_holder;