/*
* File : DownloadManagerImpl.java
* Created : 06-Jan-2004
* 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.pluginsimpl.local.download;
/**
* @author parg
*
*/
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.disk.DiskManager;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.download.DownloadManagerInitialisationAdapter;
import org.gudy.azureus2.core3.download.DownloadManagerStateFactory;
import org.gudy.azureus2.core3.download.impl.DownloadManagerDefaultPaths;
import org.gudy.azureus2.core3.download.impl.DownloadManagerMoveHandler;
import org.gudy.azureus2.core3.global.GlobalManager;
import org.gudy.azureus2.core3.global.GlobalManagerDownloadRemovalVetoException;
import org.gudy.azureus2.core3.global.GlobalManagerDownloadWillBeRemovedListener;
import org.gudy.azureus2.core3.global.GlobalManagerListener;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.plugins.download.*;
import org.gudy.azureus2.plugins.download.savelocation.DefaultSaveLocationManager;
import org.gudy.azureus2.plugins.download.savelocation.SaveLocationManager;
import org.gudy.azureus2.plugins.torrent.Torrent;
import org.gudy.azureus2.plugins.torrent.TorrentException;
import org.gudy.azureus2.plugins.ui.UIManagerEvent;
import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl;
import org.gudy.azureus2.pluginsimpl.local.ui.UIManagerImpl;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.util.CopyOnWriteList;
public class
DownloadManagerImpl
implements org.gudy.azureus2.plugins.download.DownloadManager, DownloadManagerInitialisationAdapter
{
protected static DownloadManagerImpl singleton;
protected static AEMonitor class_mon = new AEMonitor( "DownloadManager:class");
public static DownloadManagerImpl
getSingleton(
AzureusCore azureus_core )
{
try{
class_mon.enter();
if ( singleton == null ){
singleton = new DownloadManagerImpl( azureus_core );
}
return( singleton );
}finally{
class_mon.exit();
}
}
//private AzureusCore azureus_core;
private GlobalManager global_manager;
private DownloadManagerStats stats;
private DownloadEventNotifierImpl global_dl_notifier;
private List<DownloadManagerListener> listeners = new ArrayList<DownloadManagerListener>();
private CopyOnWriteList<DownloadWillBeAddedListener> dwba_listeners = new CopyOnWriteList<DownloadWillBeAddedListener>();
private AEMonitor listeners_mon = new AEMonitor( "DownloadManager:L");
private List<Download> downloads = new ArrayList<Download>();
private Map<DownloadManager,DownloadImpl> pending_dls = new IdentityHashMap<DownloadManager,DownloadImpl>();
private Map<DownloadManager,DownloadImpl> download_map = new IdentityHashMap<DownloadManager,DownloadImpl>();
protected
DownloadManagerImpl(
AzureusCore _azureus_core )
{
//azureus_core = _azureus_core;
global_manager = _azureus_core.getGlobalManager();
stats = new DownloadManagerStatsImpl( global_manager );
global_dl_notifier = new DownloadEventNotifierImpl(this);
readStubConfig();
global_manager.addListener(
new GlobalManagerListener()
{
public void
downloadManagerAdded(
DownloadManager dm )
{
addDownloadManager( dm );
}
public void
downloadManagerRemoved(
DownloadManager dm )
{
List<DownloadManagerListener> listeners_ref = null;
DownloadImpl dl = null;
try{
listeners_mon.enter();
dl = download_map.get( dm );
if ( dl == null ){
System.out.println( "DownloadManager:unknown manager removed");
}else{
downloads.remove( dl );
download_map.remove( dm );
pending_dls.remove( dm );
dl.destroy();
listeners_ref = listeners;
}
}finally{
listeners_mon.exit();
}
if ( dl != null ){
for (int i=0;i<listeners_ref.size();i++){
try{
listeners_ref.get(i).downloadRemoved( dl );
}catch( Throwable e ){
Debug.out( e );
}
}
}
}
public void
destroyInitiated()
{
}
public void
destroyed()
{
synchronized( download_stubs ){
if ( dirty_stubs ){
writeStubConfig();
}
}
}
public void seedingStatusChanged( boolean seeding_only_mode, boolean b ){
//TODO
}
});
global_manager.addDownloadWillBeRemovedListener(
new GlobalManagerDownloadWillBeRemovedListener()
{
public void
downloadWillBeRemoved(
DownloadManager dm,
boolean remove_torrent,
boolean remove_data )
throws GlobalManagerDownloadRemovalVetoException
{
DownloadImpl download = (DownloadImpl)download_map.get( dm );
if ( download != null ){
try{
download.isRemovable();
}catch( DownloadRemovalVetoException e ){
throw( new GlobalManagerDownloadRemovalVetoException( e.getMessage(),e.isSilent()));
}
}
}
});
}
public void
addDownload(
final File fileName )
{
UIManagerImpl.fireEvent( null, UIManagerEvent.ET_OPEN_TORRENT_VIA_FILE, fileName );
}
public void
addDownload(
final URL url)
{
addDownload(url,null,true,null);
}
public void
addDownload(
URL url,
boolean auto_download )
throws DownloadException
{
addDownload(url,null,auto_download,null);
}
public void
addDownload(
final URL url,
final URL referrer)
{
addDownload(url,referrer,true,null);
}
public void
addDownload(
URL url,
Map request_properties )
{
addDownload(url,null,true,request_properties);
}
public void
addDownload(
final URL url,
final URL referrer,
boolean auto_download,
Map request_properties )
{
UIManagerImpl.fireEvent( null, UIManagerEvent.ET_OPEN_TORRENT_VIA_URL, new Object[]{ url, referrer, new Boolean( auto_download ), request_properties });
}
protected void
addDownloadManager(
DownloadManager dm )
{
List<DownloadManagerListener> listeners_ref = null;
DownloadImpl dl = null;
try{
listeners_mon.enter();
if ( download_map.get(dm) == null ){
dl = pending_dls.remove( dm );
if ( dl == null ){
dl = new DownloadImpl( this, dm);
}
downloads.add( dl );
download_map.put( dm, dl );
listeners_ref = listeners;
}
}finally{
listeners_mon.exit();
}
if ( dl != null ){
for (int i=0;i<listeners_ref.size();i++){
try{
listeners_ref.get(i).downloadAdded( dl );
}catch( Throwable e ){
Debug.printStackTrace( e );
}
}
}
}
public Download
addDownload(
Torrent torrent )
throws DownloadException
{
return( addDownload( torrent, null, null ));
}
public Download
addDownload(
Torrent torrent,
File torrent_file,
File data_location )
throws DownloadException
{
return( addDownload( torrent, torrent_file, data_location, getInitialState()));
}
public Download
addDownload(
Torrent torrent,
File torrent_file,
File data_location,
int initial_state )
throws DownloadException
{
if ( torrent_file == null ){
String torrent_dir = null;
if( COConfigurationManager.getBooleanParameter("Save Torrent Files")){
try{
torrent_dir = COConfigurationManager.getDirectoryParameter("General_sDefaultTorrent_Directory");
}catch(Exception egnore){}
}
if ( torrent_dir == null || torrent_dir.length() == 0 ){
throw( new DownloadException("DownloadManager::addDownload: default torrent save directory must be configured" ));
}
torrent_file = new File( torrent_dir + File.separator + torrent.getName() + ".torrent" );
try{
torrent.writeToFile( torrent_file );
}catch( TorrentException e ){
throw( new DownloadException("DownloadManager::addDownload: failed to write torrent to '" + torrent_file.toString() + "'", e ));
}
}
else {
if (!torrent_file.exists()) {
throw new DownloadException("DownloadManager::addDownload: torrent file does not exist - " + torrent_file.toString());
}
else if (!torrent_file.isFile()) {
throw new DownloadException("DownloadManager::addDownload: torrent filepath given is not a file - " + torrent_file.toString());
}
}
if ( data_location == null ){
String data_dir = COConfigurationManager.getStringParameter("Default save path");
if ( data_dir == null || data_dir.length() == 0 ){
throw( new DownloadException("DownloadManager::addDownload: default data save directory must be configured" ));
}
data_location = new File(data_dir);
FileUtil.mkdirs(data_location);
}
byte[] hash = null;
try {
hash = torrent.getHash();
} catch (Exception e) { }
boolean for_seeding = torrent.isComplete();
DownloadManager dm = global_manager.addDownloadManager(
torrent_file.toString(), hash, data_location.toString(),
initial_state, true, for_seeding, null );
if ( dm == null ){
throw( new DownloadException( "DownloadManager::addDownload - failed, download may already in the process of being added"));
}
addDownloadManager( dm );
return( getDownload( dm ));
}
public Download
addDownloadStopped(
Torrent torrent,
File torrent_location,
File data_location )
throws DownloadException
{
return( addDownload( torrent, torrent_location, data_location, DownloadManager.STATE_STOPPED ));
}
public Download
addNonPersistentDownload(
Torrent torrent,
File torrent_file,
File data_location )
throws DownloadException
{
byte[] hash = null;
try {
hash = torrent.getHash();
} catch (Exception e) { }
DownloadManager dm = global_manager.addDownloadManager(
torrent_file.toString(), hash, data_location.toString(),
getInitialState(), false);
if ( dm == null ){
throw( new DownloadException( "DownloadManager::addDownload - failed"));
}
addDownloadManager( dm );
return( getDownload( dm ));
}
public Download
addNonPersistentDownloadStopped(
Torrent torrent,
File torrent_file,
File data_location )
throws DownloadException
{
byte[] hash = null;
try {
hash = torrent.getHash();
} catch (Exception e) { }
DownloadManager dm = global_manager.addDownloadManager(
torrent_file.toString(), hash, data_location.toString(),
DownloadManager.STATE_STOPPED, false);
if ( dm == null ){
throw( new DownloadException( "DownloadManager::addDownload - failed"));
}
addDownloadManager( dm );
return( getDownload( dm ));
}
public void
clearNonPersistentDownloadState(
byte[] hash)
{
global_manager.clearNonPersistentDownloadState( hash );
}
protected int
getInitialState()
{
boolean default_start_stopped = COConfigurationManager.getBooleanParameter( "Default Start Torrents Stopped" );
return( default_start_stopped?DownloadManager.STATE_STOPPED:DownloadManager.STATE_WAITING);
}
protected DownloadImpl
getDownload(
DownloadManager dm )
throws DownloadException
{
DownloadImpl dl = download_map.get(dm);
if ( dl == null ){
throw( new DownloadException("DownloadManager::getDownload: download not found"));
}
return( dl );
}
public static DownloadImpl[] getDownloadStatic(DownloadManager[] dm) {
ArrayList res = new ArrayList(dm.length);
for (int i=0; i<dm.length; i++) {
try {res.add(getDownloadStatic(dm[i]));}
catch (DownloadException de) {}
}
return (DownloadImpl[])res.toArray(new DownloadImpl[res.size()]);
}
/**
* Retrieve the plugin Downlaod object related to the DownloadManager
*
* @param dm DownloadManager to find
* @return plugin object
* @throws DownloadException
*/
public static DownloadImpl
getDownloadStatic(
DownloadManager dm )
throws DownloadException
{
if ( singleton != null ){
return( singleton.getDownload( dm ));
}
throw( new DownloadException( "DownloadManager not initialised"));
}
public static Download
getDownloadStatic(
DiskManager dm )
throws DownloadException
{
if ( singleton != null ){
return( singleton.getDownload( dm ));
}
throw( new DownloadException( "DownloadManager not initialised"));
}
public Download
getDownload(
DiskManager dm )
throws DownloadException
{
List<DownloadManager> dls = global_manager.getDownloadManagers();
for (int i=0;i<dls.size();i++){
DownloadManager man = dls.get(i);
if ( man.getDiskManager() == dm ){
return( getDownload( man.getTorrent()));
}
}
return( null );
}
protected Download
getDownload(
TOTorrent torrent )
throws DownloadException
{
if ( torrent != null ){
for (int i=0;i<downloads.size();i++){
Download dl = (Download)downloads.get(i);
TorrentImpl t = (TorrentImpl)dl.getTorrent();
// can be null if broken torrent
if ( t == null ){
continue;
}
if ( t.getTorrent().hasSameHashAs( torrent )){
return( dl );
}
}
}
throw( new DownloadException("DownloadManager::getDownload: download not found"));
}
public static Download
getDownloadStatic(
TOTorrent torrent )
throws DownloadException
{
if ( singleton != null ){
return( singleton.getDownload( torrent ));
}
throw( new DownloadException( "DownloadManager not initialised"));
}
public Download
getDownload(
Torrent _torrent )
{
TorrentImpl torrent = (TorrentImpl)_torrent;
try{
return( getDownload( torrent.getTorrent()));
}catch( DownloadException e ){
}
return( null );
}
public Download
getDownload(
byte[] hash )
{
DownloadManager manager = global_manager.getDownloadManager(new HashWrapper(hash));
if (manager != null) {
try {
return getDownload(manager);
} catch (DownloadException e) {
}
}
List dls = global_manager.getDownloadManagers();
for (int i=0;i<dls.size();i++){
DownloadManager man = (DownloadManager)dls.get(i);
// torrent can be null if download manager torrent file read fails
TOTorrent torrent = man.getTorrent();
if ( torrent != null ){
try{
if ( Arrays.equals( torrent.getHash(), hash )){
return( getDownload( torrent ));
}
}catch( DownloadException e ){
// not found
}catch( TOTorrentException e ){
Debug.printStackTrace( e );
}
}
}
return( null );
}
public Download[]
getDownloads()
{
// we have to use the global manager's ordering as it
// hold this
List<DownloadManager> dms = global_manager.getDownloadManagers();
Set<Download> res_l;
try{
listeners_mon.enter();
res_l = new LinkedHashSet<Download>( downloads.size());
for (int i=0;i<dms.size();i++){
DownloadImpl dl = download_map.get( dms.get(i));
if ( dl != null ){
res_l.add( dl );
}
}
if ( res_l.size() < downloads.size()){
// now add in any external downloads
for (int i=0;i<downloads.size();i++){
Download download = downloads.get(i);
if ( !res_l.contains( download )){
res_l.add( download );
}
}
}
}finally{
listeners_mon.exit();
}
Download[] res = new Download[res_l.size()];
res_l.toArray( res );
return( res );
}
public Download[]
getDownloads(boolean bSorted)
{
if (bSorted){
return getDownloads();
}
try{
listeners_mon.enter();
Download[] res = new Download[downloads.size()];
downloads.toArray( res );
return( res );
}finally{
listeners_mon.exit();
}
}
public void
pauseDownloads()
{
global_manager.pauseDownloads();
}
public boolean
canPauseDownloads()
{
return global_manager.canPauseDownloads();
}
public void
resumeDownloads()
{
global_manager.resumeDownloads();
}
public boolean
canResumeDownloads()
{
return global_manager.canResumeDownloads();
}
public void
startAllDownloads()
{
global_manager.startAllDownloads();
}
public void
stopAllDownloads()
{
global_manager.stopAllDownloads();
}
public DownloadManagerStats
getStats()
{
return( stats );
}
public boolean
isSeedingOnly()
{
return( global_manager.isSeedingOnly());
}
public void addListener(DownloadManagerListener l) {addListener(l, true);}
public void addListener(DownloadManagerListener l, boolean notify_of_current_downloads) {
List<Download> downloads_copy = null;
try {
listeners_mon.enter();
List<DownloadManagerListener> new_listeners = new ArrayList<DownloadManagerListener>(listeners);
new_listeners.add(l);
listeners = new_listeners;
if (notify_of_current_downloads) {
downloads_copy = new ArrayList<Download>(downloads);
// randomize list so that plugins triggering dlm-state fixups don't lock each other by doing everything in the same order
Collections.shuffle(downloads_copy);
}
}
finally {
listeners_mon.exit();
}
if (downloads_copy != null) {
for (int i = 0; i < downloads_copy.size(); i++) {
try {l.downloadAdded( downloads_copy.get(i));}
catch (Throwable e) {Debug.printStackTrace(e);}
}
}
}
public void removeListener(DownloadManagerListener l) {removeListener(l, false);}
public void removeListener(DownloadManagerListener l, boolean notify_of_current_downloads) {
List<Download> downloads_copy = null;
try {
listeners_mon.enter();
List<DownloadManagerListener> new_listeners = new ArrayList<DownloadManagerListener>(listeners);
new_listeners.remove(l);
listeners = new_listeners;
if (notify_of_current_downloads) {
downloads_copy = new ArrayList<Download>(downloads);
}
}
finally {
listeners_mon.exit();
}
if (downloads_copy != null) {
for (int i = 0; i < downloads_copy.size(); i++) {
try {l.downloadRemoved( downloads_copy.get(i));}
catch (Throwable e) {Debug.printStackTrace(e);}
}
}
}
public void
initialised(
DownloadManager manager,
boolean for_seeding )
{
DownloadImpl dl;
try{
listeners_mon.enter();
dl = new DownloadImpl( this, manager );
pending_dls.put( manager, dl );
}finally{
listeners_mon.exit();
}
Iterator<DownloadWillBeAddedListener> it = dwba_listeners.iterator();
while( it.hasNext()){
try{
it.next().initialised(dl);
}catch( Throwable e ){
Debug.printStackTrace(e);
}
}
}
public int
getActions()
{
// assumption is that plugin based download-will-be-added listeners might assign tags so
// indicate this
if ( dwba_listeners.size() > 0 ){
return( ACT_ASSIGNS_TAGS );
}
return( ACT_NONE );
}
public void
addDownloadWillBeAddedListener(
DownloadWillBeAddedListener listener )
{
try{
listeners_mon.enter();
dwba_listeners.add( listener );
if ( dwba_listeners.size() == 1 ){
global_manager.addDownloadManagerInitialisationAdapter( this );
}
}finally{
listeners_mon.exit();
}
}
public void
removeDownloadWillBeAddedListener(
DownloadWillBeAddedListener listener )
{
try{
listeners_mon.enter();
dwba_listeners.remove( listener );
if ( dwba_listeners.size() == 0 ){
global_manager.removeDownloadManagerInitialisationAdapter( this );
}
}finally{
listeners_mon.exit();
}
}
public void
addExternalDownload(
Download download )
{
List<DownloadManagerListener> listeners_ref = null;
try{
listeners_mon.enter();
if ( downloads.contains( download )){
return;
}
downloads.add( download );
listeners_ref = listeners;
}finally{
listeners_mon.exit();
}
for (int i=0;i<listeners_ref.size();i++){
try{
listeners_ref.get(i).downloadAdded( download );
}catch( Throwable e ){
Debug.printStackTrace( e );
}
}
}
public void
removeExternalDownload(
Download download )
{
List<DownloadManagerListener> listeners_ref = null;
try{
listeners_mon.enter();
if ( !downloads.contains( download )){
return;
}
downloads.remove( download );
listeners_ref = listeners;
}finally{
listeners_mon.exit();
}
for (int i=0;i<listeners_ref.size();i++){
try{
listeners_ref.get(i).downloadRemoved( download );
}catch( Throwable e ){
Debug.printStackTrace( e );
}
}
}
public DownloadEventNotifier getGlobalDownloadEventNotifier() {
return this.global_dl_notifier;
}
public void setSaveLocationManager(SaveLocationManager manager) {
if (manager == null) {manager = getDefaultSaveLocationManager();}
DownloadManagerMoveHandler.CURRENT_HANDLER = manager;
}
public SaveLocationManager getSaveLocationManager() {
return DownloadManagerMoveHandler.CURRENT_HANDLER;
}
public DefaultSaveLocationManager getDefaultSaveLocationManager() {
return DownloadManagerDefaultPaths.DEFAULT_HANDLER;
}
// stubbin it
private static final String STUB_CONFIG_FILE = "dlarchive.config";
private static final File ARCHIVE_DIR;
static{
ARCHIVE_DIR = FileUtil.getUserFile( "dlarchive" );
if ( !ARCHIVE_DIR.exists()){
FileUtil.mkdirs(ARCHIVE_DIR);
}
}
private List<DownloadStubImpl> download_stubs = new ArrayList<DownloadStubImpl>();
private CopyOnWriteList<DownloadStubListener> download_stub_listeners = new CopyOnWriteList<DownloadStubListener>();
private FrequencyLimitedDispatcher dirty_stub_dispatcher =
new FrequencyLimitedDispatcher(
new AERunnable()
{
public void
runSupport()
{
synchronized( download_stubs ){
writeStubConfig();
}
}
},
10*1000 );
private boolean dirty_stubs = false;
private void
readStubConfig()
{
if ( FileUtil.resilientConfigFileExists( STUB_CONFIG_FILE )){
Map map = FileUtil.readResilientConfigFile( STUB_CONFIG_FILE );
List<Map> list = (List<Map>)map.get( "stubs" );
if ( list != null ){
for ( Map m: list ){
download_stubs.add( new DownloadStubImpl( this, m ));
}
}
}
}
private void
writeStubConfig()
{
if ( download_stubs.size() == 0 ){
FileUtil.deleteResilientConfigFile( STUB_CONFIG_FILE );
}else{
Map map = new HashMap();
List list = new ArrayList( download_stubs.size());
map.put( "stubs", list );
for ( DownloadStubImpl stub: download_stubs ){
list.add( stub.exportToMap());
}
FileUtil.writeResilientConfigFile( STUB_CONFIG_FILE, map );
}
dirty_stubs = false;
}
public boolean
canStubbify(
DownloadImpl download )
{
if ( download.getState() != Download.ST_STOPPED ){
return( false );
}
if ( !download.isPersistent()){
return( false );
}
if ( download.getTorrent() == null ){
return( false );
}
if ( download.getFlag( Download.FLAG_LOW_NOISE ) || download.getFlag( Download.FLAG_METADATA_DOWNLOAD )){
return( false );
}
if ( !download.isComplete( false )){
return( false );
}
return( true );
}
protected DownloadStub
stubbify(
DownloadImpl download )
throws DownloadException, DownloadRemovalVetoException
{
if ( !canStubbify( download )){
throw( new DownloadException( "Download not in stubbifiable state" ));
}
DownloadManager core_dm = PluginCoreUtils.unwrap( download );
Map gm_data = global_manager.exportDownloadStateToMap( core_dm );
// meh, gm assumes this map is always serialised + deserialised and doesn't expect
// String values
try{
gm_data = BDecoder.decode( BEncoder.encode( gm_data ));
}catch( IOException e ){
Debug.out( e );
}
DownloadStubImpl stub = new DownloadStubImpl( this, download, gm_data );
try{
informAdded( stub, true );
}finally{
stub.setStubbified();
}
boolean added = false;
try{
core_dm.getDownloadState().exportState( ARCHIVE_DIR );
download.remove( false, false );
synchronized( download_stubs ){
download_stubs.add( stub );
writeStubConfig();
}
added = true;
informAdded( stub, false );
}finally{
if ( !added ){
// inform that the 'will be added' failed
informRemoved( stub, true );
}
}
return( stub );
}
protected Download
destubbify(
DownloadStubImpl stub )
throws DownloadException
{
boolean removed = false;
informRemoved( stub, true );
try{
byte[] torrent_hash = stub.getTorrentHash();
try{
DownloadManagerStateFactory.importDownloadState( ARCHIVE_DIR, torrent_hash );
}catch( Throwable e ){
throw( new DownloadException( "Failed to import download state", e ));
}
DownloadManager core_dm = global_manager.importDownloadStateFromMap( stub.getGMMap());
if ( core_dm == null ){
try{
DownloadManagerStateFactory.deleteDownloadState( torrent_hash );
}catch( Throwable e ){
Debug.out( e );
}
throw( new DownloadException( "Failed to add download" ));
}else{
try{
DownloadManagerStateFactory.deleteDownloadState( ARCHIVE_DIR, torrent_hash );
}catch( Throwable e ){
Debug.out( e );
}
synchronized( download_stubs ){
download_stubs.remove( stub );
writeStubConfig();
}
removed = true;
informRemoved( stub, false );
return( PluginCoreUtils.wrap( core_dm ));
}
}finally{
if ( !removed ){
// inform that the 'will be removed' failed
informAdded( stub, true );
}
}
}
protected void
remove(
DownloadStubImpl stub )
{
boolean removed = false;
informRemoved( stub, true );
try{
try{
DownloadManagerStateFactory.deleteDownloadState( ARCHIVE_DIR, stub.getTorrentHash());
}catch( Throwable e ){
Debug.out( e );
}
synchronized( download_stubs ){
download_stubs.remove( stub );
writeStubConfig();
}
removed = true;
informRemoved( stub, false );
}finally{
if ( !removed ){
informAdded( stub, true );
}
}
}
protected void
updated(
DownloadStubImpl stub )
{
synchronized( download_stubs ){
dirty_stubs = true;
}
dirty_stub_dispatcher.dispatch();
}
public DownloadStub[]
getDownloadStubs()
{
synchronized( download_stubs ){
return( download_stubs.toArray( new DownloadStub[download_stubs.size()]));
}
}
private void
informAdded(
DownloadStub stub,
final boolean preparing )
{
final List<DownloadStub> list = new ArrayList<DownloadStub>();
list.add( stub );
for ( DownloadStubListener l: download_stub_listeners ){
try{
l.downloadStubEventOccurred(
new DownloadStubEvent()
{
public int
getEventType()
{
return( preparing?DownloadStubEvent.DSE_STUB_WILL_BE_ADDED:DownloadStubEvent.DSE_STUB_ADDED );
}
public List<DownloadStub>
getDownloadStubs()
{
return( list );
}
});
}catch( Throwable e ){
Debug.out( e );
}
}
}
private void
informRemoved(
DownloadStub stub,
final boolean preparing )
{
final List<DownloadStub> list = new ArrayList<DownloadStub>();
list.add( stub );
for ( DownloadStubListener l: download_stub_listeners ){
try{
l.downloadStubEventOccurred(
new DownloadStubEvent()
{
public int
getEventType()
{
return( preparing?DownloadStubEvent.DSE_STUB_WILL_BE_REMOVED:DownloadStubEvent.DSE_STUB_REMOVED );
}
public List<DownloadStub>
getDownloadStubs()
{
return( list );
}
});
}catch( Throwable e ){
Debug.out( e );
}
}
}
public void
addDownloadStubListener(
DownloadStubListener l,
boolean inform_of_current )
{
download_stub_listeners.add( l );
if ( inform_of_current ){
final List<DownloadStub> existing;
synchronized( download_stubs ){
existing = new ArrayList<DownloadStub>( download_stubs );
}
try{
l.downloadStubEventOccurred(
new DownloadStubEvent()
{
public int
getEventType()
{
return( DownloadStubEvent.DSE_STUB_ADDED );
}
public List<DownloadStub>
getDownloadStubs()
{
return( existing );
}
});
}catch( Throwable e ){
Debug.out( e );
}
}
}
public void
removeDownloadStubListener(
DownloadStubListener l )
{
download_stub_listeners.remove( l );
}
}