FileDocCategorySizeDatePackage
MagnetPlugin.javaAPI DocAzureus 3.0.3.416617Fri May 04 17:14:46 BST 2007com.aelitis.azureus.plugins.magnet

MagnetPlugin

public class MagnetPlugin extends Object implements Plugin
author
parg

Fields Summary
private PluginInterface
plugin_interface
private com.aelitis.azureus.core.util.CopyOnWriteList
listeners
Constructors Summary
Methods Summary
public voidaddListener(MagnetPluginListener listener)

		listeners.add( listener );
	
public byte[]badge()

		return( null );
	
public byte[]download(MagnetPluginProgressListener listener, byte[] hash, java.net.InetSocketAddress[] sources, long timeout)

		try{
			listener.reportActivity( getMessageText( "report.waiting_ddb" ));

			final DistributedDatabase db = plugin_interface.getDistributedDatabase();
			
			final List			potential_contacts 		= new ArrayList();
			final AESemaphore	potential_contacts_sem 	= new AESemaphore( "MagnetPlugin:liveones" );
			final AEMonitor		potential_contacts_mon	= new AEMonitor( "MagnetPlugin:liveones" );
			
			final int[]			outstanding		= {0};

			listener.reportActivity(  getMessageText( "report.searching" ));
			
			DistributedDatabaseListener	ddb_listener = 
				new DistributedDatabaseListener()
				{
					public void
					event(
						DistributedDatabaseEvent 		event )
					{
						int	type = event.getType();
	
						if ( type == DistributedDatabaseEvent.ET_VALUE_READ ){
													
							contactFound( event.getValue().getContact());
			
						}else if (	type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ||
									type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ){
								
								// now inject any explicit sources
							
							for (int i=0;i<sources.length;i++){
								
								try{
									contactFound( db.importContact(sources[i]));
									
								}catch( Throwable e ){
									
									Debug.printStackTrace(e);
								}
							}
							
							potential_contacts_sem.release();
						}
					}
					
					public void
					contactFound(
						final DistributedDatabaseContact	contact )
					{
						listener.reportActivity( getMessageText( "report.found", contact.getName()));
				
						outstanding[0]++;
						
						Thread t = 
							new AEThread( "MagnetPlugin:HitHandler")
							{
								public void
								runSupport()
								{
									try{
										boolean	alive = contact.isAlive(20*1000);
																						
										listener.reportActivity( 
												getMessageText( alive?"report.alive":"report.dead",	contact.getName()));
										
										try{
											potential_contacts_mon.enter();
											
											Object[]	entry = new Object[]{ new Boolean( alive ), contact};
											
											boolean	added = false;
											
											if ( alive ){
												
													// try and place before first dead entry 
										
												for (int i=0;i<potential_contacts.size();i++){
													
													if (!((Boolean)((Object[])potential_contacts.get(i))[0]).booleanValue()){
														
														potential_contacts.add(i, entry );
														
														added = true;
														
														break;
													}
												}
											}
											
											if ( !added ){
												
												potential_contacts.add( entry );	// dead at end
											}
												
											potential_contacts_sem.release();
												
										}finally{
												
											potential_contacts_mon.exit();
										}
									}finally{
										
										try{
											potential_contacts_mon.enter();													

											outstanding[0]--;
											
										}finally{
											
											potential_contacts_mon.exit();
										}
									}
								}
							};
							
						t.setDaemon(true);
						
						t.start();
					}
				};
				
			db.read(
				ddb_listener,
				db.createKey( hash, "Torrent download lookup for '" + ByteFormatter.encodeString( hash ) + "'" ),
				timeout,
				DistributedDatabase.OP_EXHAUSTIVE_READ | DistributedDatabase.OP_PRIORITY_HIGH );
			
			long	remaining	= timeout;
			
			while( remaining > 0 ){
					
				long start = SystemTime.getCurrentTime();
				
				potential_contacts_sem.reserve( remaining );
				
				remaining -= ( SystemTime.getCurrentTime() - start );
				
				DistributedDatabaseContact	contact;
				boolean						live_contact;
				
				try{
					potential_contacts_mon.enter();
					
					if ( potential_contacts.size() == 0 ){
						
						if ( outstanding[0] == 0 ){
						
							break;
							
						}else{
							
							continue;
						}
					}else{
					
						Object[]	entry = (Object[])potential_contacts.remove(0);
						
						live_contact 	= ((Boolean)entry[0]).booleanValue(); 
						contact 		= (DistributedDatabaseContact)entry[1];
					}
					
				}finally{
					
					potential_contacts_mon.exit();
				}
					
				// System.out.println( "magnetDownload: " + contact.getName() + ", live = " + live_contact );
				
				if ( !live_contact ){
					
					listener.reportActivity( getMessageText( "report.tunnel", contact.getName()));

					contact.openTunnel();
				}
				
				try{
					listener.reportActivity( getMessageText( "report.downloading", contact.getName()));
					
					DistributedDatabaseValue	value = 
						contact.read( 
								new DistributedDatabaseProgressListener()
								{
									public void
									reportSize(
										long	size )
									{
										listener.reportSize( size );
									}
									public void
									reportActivity(
										String	str )
									{
										listener.reportActivity( str );
									}
									
									public void
									reportCompleteness(
										int		percent )
									{
										listener.reportCompleteness( percent );
									}
								},
								db.getStandardTransferType( DistributedDatabaseTransferType.ST_TORRENT ),
								db.createKey ( hash , "Torrent download content for '" + ByteFormatter.encodeString( hash ) + "'"),
								timeout );
										
					if ( value != null ){
						
						return( (byte[])value.getValue(byte[].class));
					}
				}catch( Throwable e ){
					
					listener.reportActivity( getMessageText( "report.error", Debug.getNestedExceptionMessage(e)));
					
					Debug.printStackTrace(e);
				}
			}
		
			return( null );		// nothing found
			
		}catch( Throwable e ){
			
			Debug.printStackTrace(e);
			
			listener.reportActivity( getMessageText( "report.error", Debug.getNestedExceptionMessage(e)));

			throw( new MagnetURIHandlerException( "MagnetURIHandler failed", e ));
		}
	
public java.net.URLgetMagnetURL(org.gudy.azureus2.plugins.download.Download d)

		Torrent	torrent = d.getTorrent();
		
		if ( torrent == null ){
			
			return( null );
		}
		
		return( getMagnetURL( torrent.getHash()));
	
public java.net.URLgetMagnetURL(byte[] hash)

		try{
			return( new URL( "magnet:?xt=urn:btih:" + Base32.encode(hash)));
		
		}catch( Throwable e ){
		
			Debug.printStackTrace(e);
		
			return( null );
		}
	
protected java.lang.StringgetMessageText(java.lang.String resource)

		return( plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( "MagnetPlugin." + resource ));
	
protected java.lang.StringgetMessageText(java.lang.String resource, java.lang.String param)

		return( plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( 
				"MagnetPlugin." + resource, new String[]{ param }));
	
public voidinitialize(PluginInterface _plugin_interface)

	
	 
	
			 
	
		plugin_interface	= _plugin_interface;
		
		plugin_interface.getPluginProperties().setProperty( "plugin.version", 	"1.0" );
		plugin_interface.getPluginProperties().setProperty( "plugin.name", 		"Magnet URI Handler" );
		
		MenuItemListener	listener = 
			new MenuItemListener()
			{
				public void
				selected(
					MenuItem		_menu,
					Object			_target )
				{
					Download download = (Download)((TableRow)_target).getDataSource();
				  
					if ( download == null || download.getTorrent() == null ){
						
						return;
					}
					
					Torrent torrent = download.getTorrent();
					
					String	cb_data = "magnet:?xt=urn:btih:" + Base32.encode( torrent.getHash());

					// removed this as well - nothing wrong with allowing magnet copy
					// for private torrents - they still can't be tracked if you don't
					// have permission
					
					
					/*if ( torrent.isPrivate()){
						
						cb_data = getMessageText( "private_torrent" );
						
					}else if ( torrent.isDecentralised()){
					*/	
						// ok
						
						/* relaxed this as we allow such torrents to be downloaded via magnet links
						 * (as opposed to tracked in the DHT)
						 
					}else if ( torrent.isDecentralisedBackupEnabled()){
							
						TorrentAttribute ta_peer_sources 	= plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_PEER_SOURCES );

						String[]	sources = download.getListAttribute( ta_peer_sources );
		
						boolean	ok = false;
								
						for (int i=0;i<sources.length;i++){
									
							if ( sources[i].equalsIgnoreCase( "DHT")){
										
								ok	= true;
										
								break;
							}
						}
		
						if ( !ok ){
							
							cb_data = getMessageText( "decentral_disabled" );
						}
					}else{
						
						cb_data = getMessageText( "decentral_backup_disabled" );
						*/
					// }
					
					// System.out.println( "MagnetPlugin: export = " + url );
					
					try{
						plugin_interface.getUIManager().copyToClipBoard( cb_data );
						
					}catch( Throwable  e ){
						
						e.printStackTrace();
					}
				}
			};
		
		final TableContextMenuItem menu1 = plugin_interface.getUIManager().getTableManager().addContextMenuItem(TableManager.TABLE_MYTORRENTS_INCOMPLETE, "MagnetPlugin.contextmenu.exporturi" );
		final TableContextMenuItem menu2 = plugin_interface.getUIManager().getTableManager().addContextMenuItem(TableManager.TABLE_MYTORRENTS_COMPLETE, 	"MagnetPlugin.contextmenu.exporturi" );
			
		menu1.addListener( listener );
		menu2.addListener( listener );

		MagnetURIHandler.getSingleton().addListener(
			new MagnetURIHandlerListener()
			{
				public byte[]
				badge()
				{
					InputStream is = getClass().getClassLoader().getResourceAsStream( "com/aelitis/azureus/plugins/magnet/Magnet.gif" );
					
					if ( is == null ){
						
						return( null );
					}
					
					try{
						ByteArrayOutputStream	baos = new ByteArrayOutputStream();
						
						try{
							byte[]	buffer = new byte[8192];
							
							while( true ){
	
								int	len = is.read( buffer );
				
								if ( len <= 0 ){
									
									break;
								}
		
								baos.write( buffer, 0, len );
							}
						}finally{
							
							is.close();
						}
						
						return( baos.toByteArray());
						
					}catch( Throwable e ){
						
						Debug.printStackTrace(e);
						
						return( null );
					}
				}
							
				public byte[]
				download(
					final MagnetURIHandlerProgressListener		muh_listener,
					final byte[]								hash,
					final InetSocketAddress[]					sources,
					final long									timeout )
				
					throws MagnetURIHandlerException
				{
						// see if we've already got it!
					
					try{
						Download	dl = plugin_interface.getDownloadManager().getDownload( hash );
					
						if ( dl != null ){
							
							Torrent	torrent = dl.getTorrent();
							
							if ( torrent != null ){
								
								return( torrent.writeToBEncodedData());
							}
						}
					}catch( Throwable e ){
					
						Debug.printStackTrace(e);
					}
					
					return( MagnetPlugin.this.download(
							new MagnetPluginProgressListener()
							{
								public void
								reportSize(
									long	size )
								{
									muh_listener.reportSize( size );
								}
								
								public void
								reportActivity(
									String	str )
								{
									muh_listener.reportActivity( str );
								}
								
								public void
								reportCompleteness(
									int		percent )
								{
									muh_listener.reportCompleteness( percent );
								}
							},
							hash,
							sources,
							timeout ));
				}
				
				public boolean
				download(
					URL		url )
				
					throws MagnetURIHandlerException
				{
					try{
						
						plugin_interface.getDownloadManager().addDownload( url, false );
						
						return( true );
						
					}catch( DownloadException e ){
						
						throw( new MagnetURIHandlerException( "Operation failed", e ));
					}
				}
				
				public boolean
				set(
					String		name,
					Map		values )
				{
					List	l = listeners.getList();
					
					for (int i=0;i<l.size();i++){
						
						if (((MagnetPluginListener)l.get(i)).set( name, values )){
							
							return( true );
						}
					}
					
					return( false );
				}
			});
		
		plugin_interface.addListener(
			new PluginListener()
			{
				public void
				initializationComplete()
				{
						// make sure DDB is initialised as we need it to register its
						// transfer types
					
					Thread t = 
						new AEThread( "MagnetPlugin:init" )
						{
							public void
							runSupport()
							{
								plugin_interface.getDistributedDatabase();
							}
						};
					
					t.setDaemon( true );
					
					t.start();
				}
				
				public void
				closedownInitiated(){}
				
				public void
				closedownComplete(){}			
			});
		
		plugin_interface.getUIManager().addUIListener(
				new UIManagerListener()
				{
					public void
					UIAttached(
						UIInstance		instance )
					{
						if ( instance instanceof UISWTInstance ){
							
							UISWTInstance	swt = (UISWTInstance)instance;
							
							Image	image = swt.loadImage( "com/aelitis/azureus/plugins/magnet/icons/magnet.gif" );

							menu1.setGraphic( swt.createGraphic( image ));
							menu2.setGraphic( swt.createGraphic( image ));							
						}
					}
					
					public void
					UIDetached(
						UIInstance		instance )
					{
						
					}
				});
	
public voidremoveListener(MagnetPluginListener listener)

		listeners.remove( listener );