1 /* 2 * File : DownloadImpl.java 3 * Created : 06-Jan-2004 4 * By : parg 5 * 6 * Azureus - a Java Bittorrent client 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details ( see the LICENSE file ). 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22 23 package org.gudy.azureus2.pluginsimpl.local.download; 24 25 /** 26 * @author parg 27 * 28 */ 29 30 import java.io.File; 31 import java.net.URL; 32 import java.util.*; 33 34 import org.gudy.azureus2.core3.category.Category; 35 import org.gudy.azureus2.core3.category.CategoryManager; 36 import org.gudy.azureus2.core3.download.*; 37 import org.gudy.azureus2.core3.download.DownloadManager; 38 import org.gudy.azureus2.core3.download.DownloadManagerListener; 39 import org.gudy.azureus2.core3.download.impl.DownloadManagerMoveHandler; 40 import org.gudy.azureus2.core3.global.GlobalManager; 41 import org.gudy.azureus2.core3.global.GlobalManagerDownloadRemovalVetoException; 42 import org.gudy.azureus2.core3.internat.MessageText; 43 import org.gudy.azureus2.core3.logging.LogRelation; 44 import org.gudy.azureus2.core3.peer.PEPeer; 45 import org.gudy.azureus2.core3.peer.PEPeerManager; 46 import org.gudy.azureus2.core3.peer.PEPeerSource; 47 import org.gudy.azureus2.core3.torrent.TOTorrent; 48 import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; 49 import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse; 50 import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse; 51 import org.gudy.azureus2.core3.util.AEMonitor; 52 import org.gudy.azureus2.core3.util.BEncoder; 53 import org.gudy.azureus2.core3.util.Debug; 54 import org.gudy.azureus2.core3.util.SystemTime; 55 import org.gudy.azureus2.core3.util.TorrentUtils; 56 import org.gudy.azureus2.plugins.ddb.DistributedDatabase; 57 import org.gudy.azureus2.plugins.disk.DiskManager; 58 import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo; 59 import org.gudy.azureus2.plugins.download.*; 60 import org.gudy.azureus2.plugins.download.savelocation.SaveLocationChange; 61 import org.gudy.azureus2.plugins.network.RateLimiter; 62 import org.gudy.azureus2.plugins.peers.PeerManager; 63 import org.gudy.azureus2.plugins.tag.Tag; 64 import org.gudy.azureus2.plugins.torrent.Torrent; 65 import org.gudy.azureus2.plugins.torrent.TorrentAttribute; 66 import org.gudy.azureus2.pluginsimpl.local.ddb.DDBaseImpl; 67 import org.gudy.azureus2.pluginsimpl.local.deprecate.PluginDeprecation; 68 import org.gudy.azureus2.pluginsimpl.local.disk.DiskManagerFileInfoImpl; 69 import org.gudy.azureus2.pluginsimpl.local.peers.PeerManagerImpl; 70 import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl; 71 import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentManagerImpl; 72 import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; 73 74 import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTHandshake; 75 import com.aelitis.azureus.core.tag.TagManagerFactory; 76 import com.aelitis.azureus.core.tracker.TrackerPeerSource; 77 import com.aelitis.azureus.core.tracker.TrackerPeerSourceAdapter; 78 import com.aelitis.azureus.core.util.CopyOnWriteList; 79 import com.aelitis.azureus.core.util.CopyOnWriteMap; 80 81 public class 82 DownloadImpl 83 extends LogRelation 84 implements Download, DownloadManagerListener, 85 DownloadManagerTrackerListener, 86 DownloadManagerStateListener, DownloadManagerActivationListener, 87 DownloadManagerStateAttributeListener 88 { 89 private final DownloadManagerImpl manager; 90 private final DownloadManager download_manager; 91 private final DownloadStatsImpl download_stats; 92 93 private int latest_state = ST_STOPPED; 94 private boolean latest_forcedStart; 95 96 private DownloadAnnounceResultImpl last_announce_result = new DownloadAnnounceResultImpl(this,null); 97 private DownloadScrapeResultImpl last_scrape_result = new DownloadScrapeResultImpl( this, null ); 98 private AggregateScrapeResult last_aggregate_scrape = new AggregateScrapeResult( this ); 99 100 private TorrentImpl torrent = null; 101 102 private List listeners = new ArrayList(); 103 private AEMonitor listeners_mon = new AEMonitor( "Download:L"); 104 private List property_listeners = new ArrayList(); 105 private List tracker_listeners = new ArrayList(); 106 private AEMonitor tracker_listeners_mon = new AEMonitor( "Download:TL"); 107 private List removal_listeners = new ArrayList(); 108 private AEMonitor removal_listeners_mon = new AEMonitor( "Download:RL"); 109 private Map peer_listeners = new HashMap(); 110 private AEMonitor peer_listeners_mon = new AEMonitor( "Download:PL"); 111 112 private CopyOnWriteList completion_listeners = new CopyOnWriteList(); 113 114 private CopyOnWriteMap read_attribute_listeners_map_cow = new CopyOnWriteMap(); 115 private CopyOnWriteMap write_attribute_listeners_map_cow = new CopyOnWriteMap(); 116 117 private CopyOnWriteList activation_listeners = new CopyOnWriteList(); 118 private DownloadActivationEvent activation_state; 119 120 121 private Map<String,int[]> announce_response_map; 122 123 protected DownloadImpl( DownloadManagerImpl _manager, DownloadManager _dm )124 DownloadImpl( 125 DownloadManagerImpl _manager, 126 DownloadManager _dm ) 127 { 128 manager = _manager; 129 download_manager = _dm; 130 download_stats = new DownloadStatsImpl( download_manager ); 131 132 activation_state = 133 new DownloadActivationEvent() 134 { 135 public Download 136 getDownload() 137 { 138 return( DownloadImpl.this ); 139 } 140 141 public int 142 getActivationCount() 143 { 144 return( download_manager.getActivationCount()); 145 } 146 }; 147 148 download_manager.addListener( this ); 149 150 latest_forcedStart = download_manager.isForceStart(); 151 } 152 153 // Not available to plugins 154 public DownloadManager getDownload()155 getDownload() 156 { 157 return( download_manager ); 158 } 159 160 public int getState()161 getState() 162 { 163 return( convertState( download_manager.getState()) ); 164 } 165 166 public int getSubState()167 getSubState() 168 { 169 int state = getState(); 170 171 if ( state == ST_STOPPING ){ 172 173 int substate = download_manager.getSubState(); 174 175 if ( substate == DownloadManager.STATE_QUEUED ){ 176 177 return( ST_QUEUED ); 178 179 }else if ( substate == DownloadManager.STATE_STOPPED ){ 180 181 return( ST_STOPPED ); 182 183 }else if ( substate == DownloadManager.STATE_ERROR ){ 184 185 return( ST_ERROR ); 186 } 187 } 188 189 return( state ); 190 } 191 192 protected int convertState( int dm_state )193 convertState( 194 int dm_state ) 195 { 196 // dm states: waiting -> initialising -> initialized -> 197 // disk states: allocating -> checking -> ready -> 198 // dm states: downloading -> finishing -> seeding -> stopping -> stopped 199 200 // "initialize" call takes from waiting -> initialising -> waiting (no port) or initialized (ok) 201 // if initialized then disk manager runs through to ready 202 // "startdownload" takes ready -> dl etc. 203 // "stopIt" takes to stopped which is equiv to ready 204 205 int our_state; 206 207 switch( dm_state ){ 208 case DownloadManager.STATE_WAITING: 209 { 210 our_state = ST_WAITING; 211 212 break; 213 } 214 case DownloadManager.STATE_INITIALIZING: 215 case DownloadManager.STATE_INITIALIZED: 216 case DownloadManager.STATE_ALLOCATING: 217 case DownloadManager.STATE_CHECKING: 218 { 219 our_state = ST_PREPARING; 220 221 break; 222 } 223 case DownloadManager.STATE_READY: 224 { 225 our_state = ST_READY; 226 227 break; 228 } 229 case DownloadManager.STATE_DOWNLOADING: 230 case DownloadManager.STATE_FINISHING: // finishing download - transit to seeding 231 { 232 our_state = ST_DOWNLOADING; 233 234 break; 235 } 236 case DownloadManager.STATE_SEEDING: 237 { 238 our_state = ST_SEEDING; 239 240 break; 241 } 242 case DownloadManager.STATE_STOPPING: 243 { 244 our_state = ST_STOPPING; 245 246 break; 247 } 248 case DownloadManager.STATE_STOPPED: 249 { 250 our_state = ST_STOPPED; 251 252 break; 253 } 254 case DownloadManager.STATE_QUEUED: 255 { 256 our_state = ST_QUEUED; 257 258 break; 259 } 260 case DownloadManager.STATE_ERROR: 261 { 262 our_state = ST_ERROR; 263 264 break; 265 } 266 default: 267 { 268 our_state = ST_ERROR; 269 } 270 } 271 272 return( our_state ); 273 } 274 275 public String getErrorStateDetails()276 getErrorStateDetails() 277 { 278 return( download_manager.getErrorDetails()); 279 } 280 281 public long getFlags()282 getFlags() 283 { 284 return( download_manager.getDownloadState().getFlags()); 285 } 286 287 public boolean getFlag( long flag )288 getFlag( 289 long flag ) 290 { 291 return( download_manager.getDownloadState().getFlag( flag )); 292 } 293 setFlag(long flag, boolean set)294 public void setFlag(long flag, boolean set) { 295 download_manager.getDownloadState().setFlag(flag, set); 296 } 297 298 public int getIndex()299 getIndex() 300 { 301 GlobalManager globalManager = download_manager.getGlobalManager(); 302 return globalManager.getIndexOf(download_manager); 303 } 304 305 public Torrent getTorrent()306 getTorrent() 307 { 308 if (this.torrent != null) {return this.torrent;} 309 310 TOTorrent torrent = download_manager.getTorrent(); 311 if (torrent == null) {return null;} 312 this.torrent = new TorrentImpl(torrent); 313 return this.torrent; 314 } 315 316 public void initialize()317 initialize() 318 319 throws DownloadException 320 { 321 int state = download_manager.getState(); 322 323 if ( state == DownloadManager.STATE_WAITING ){ 324 325 download_manager.initialize(); 326 327 }else{ 328 329 throw( new DownloadException( "Download::initialize: download not waiting (state=" + state + ")" )); 330 } 331 } 332 333 public void start()334 start() 335 336 throws DownloadException 337 { 338 int state = download_manager.getState(); 339 340 if ( state == DownloadManager.STATE_READY ){ 341 342 download_manager.startDownload(); 343 344 }else{ 345 346 throw( new DownloadException( "Download::start: download not ready (state=" + state + ")" )); 347 } 348 } 349 350 public void restart()351 restart() 352 353 throws DownloadException 354 { 355 int state = download_manager.getState(); 356 357 if ( state == DownloadManager.STATE_STOPPED || 358 state == DownloadManager.STATE_QUEUED ){ 359 360 download_manager.setStateWaiting(); 361 362 }else{ 363 364 throw( new DownloadException( "Download::restart: download already running (state=" + state + ")" )); 365 } 366 } 367 368 public void stop()369 stop() 370 371 throws DownloadException 372 { 373 if ( download_manager.getState() != DownloadManager.STATE_STOPPED){ 374 375 download_manager.stopIt( DownloadManager.STATE_STOPPED, false, false ); 376 377 }else{ 378 379 throw( new DownloadException( "Download::stop: download already stopped" )); 380 } 381 } 382 383 public void stopAndQueue()384 stopAndQueue() 385 386 throws DownloadException 387 { 388 if ( download_manager.getState() != DownloadManager.STATE_QUEUED){ 389 390 download_manager.stopIt( DownloadManager.STATE_QUEUED, false, false ); 391 392 }else{ 393 394 throw( new DownloadException( "Download::stopAndQueue: download already queued" )); 395 } 396 } 397 398 public void recheckData()399 recheckData() 400 401 throws DownloadException 402 { 403 if ( !download_manager.canForceRecheck()){ 404 405 throw( new DownloadException( "Download::recheckData: download must be stopped, queued or in error state" )); 406 } 407 408 download_manager.forceRecheck(); 409 } 410 411 public boolean isStartStopLocked()412 isStartStopLocked() 413 { 414 return( download_manager.getState() == DownloadManager.STATE_STOPPED ); 415 } 416 417 public boolean isForceStart()418 isForceStart() 419 { 420 return download_manager.isForceStart(); 421 } 422 423 public void setForceStart(boolean forceStart)424 setForceStart(boolean forceStart) 425 { 426 download_manager.setForceStart(forceStart); 427 } 428 429 public boolean isPaused()430 isPaused() 431 { 432 return( download_manager.isPaused()); 433 } 434 435 public void pause()436 pause() 437 { 438 download_manager.pause(); 439 } 440 441 public void resume()442 resume() 443 { 444 download_manager.resume(); 445 } 446 447 public int getPosition()448 getPosition() 449 { 450 return download_manager.getPosition(); 451 } 452 453 public long getCreationTime()454 getCreationTime() 455 { 456 return( download_manager.getCreationTime()); 457 } 458 459 public void setPosition(int newPosition)460 setPosition(int newPosition) 461 { 462 download_manager.setPosition(newPosition); 463 } 464 465 public void moveUp()466 moveUp() 467 { 468 download_manager.getGlobalManager().moveUp(download_manager); 469 } 470 471 public void moveDown()472 moveDown() 473 { 474 download_manager.getGlobalManager().moveDown(download_manager); 475 } 476 477 public void moveTo( int pos )478 moveTo( 479 int pos ) 480 { 481 download_manager.getGlobalManager().moveTo( download_manager, pos ); 482 } 483 484 public String getName()485 getName() 486 { 487 return download_manager.getDisplayName(); 488 } 489 getTorrentFileName()490 public String getTorrentFileName() { 491 return download_manager.getTorrentFileName(); 492 } 493 getCategoryName()494 public String getCategoryName() { 495 Category category = download_manager.getDownloadState().getCategory(); 496 if (category == null) 497 category = CategoryManager.getCategory(Category.TYPE_UNCATEGORIZED); 498 499 if (category == null) 500 return null; 501 return category.getName(); 502 } 503 getTags()504 public List<Tag> getTags() { 505 return( new ArrayList<Tag>( TagManagerFactory.getTagManager().getTagsForTaggable( download_manager ))); 506 } 507 508 public String getAttribute( TorrentAttribute attribute )509 getAttribute( 510 TorrentAttribute attribute ) 511 { 512 String name = convertAttribute( attribute ); 513 514 if ( name != null ){ 515 516 return( download_manager.getDownloadState().getAttribute( name )); 517 } 518 519 return( null ); 520 } 521 522 public String[] getListAttribute( TorrentAttribute attribute )523 getListAttribute( 524 TorrentAttribute attribute ) 525 { 526 String name = convertAttribute( attribute ); 527 528 if ( name != null ){ 529 530 return( download_manager.getDownloadState().getListAttribute( name )); 531 } 532 533 return( null ); 534 } 535 536 public void setListAttribute( TorrentAttribute attribute, String[] value)537 setListAttribute( 538 TorrentAttribute attribute, 539 String[] value) 540 { 541 String name = convertAttribute(attribute); 542 543 if (name != null) { 544 download_manager.getDownloadState().setListAttribute(name, value); 545 } 546 } 547 548 public void setMapAttribute( TorrentAttribute attribute, Map value )549 setMapAttribute( 550 TorrentAttribute attribute, 551 Map value ) 552 { 553 String name = convertAttribute( attribute ); 554 555 if ( name != null ){ 556 557 // gotta clone before updating in case user has read values and then just 558 // updated them - setter code optimises out sets of the same values... 559 560 download_manager.getDownloadState().setMapAttribute( name, BEncoder.cloneMap( value )); 561 } 562 } 563 564 public Map getMapAttribute( TorrentAttribute attribute )565 getMapAttribute( 566 TorrentAttribute attribute ) 567 { 568 String name = convertAttribute( attribute ); 569 570 if ( name != null ){ 571 572 return( download_manager.getDownloadState().getMapAttribute( name )); 573 } 574 575 return( null ); 576 } 577 578 public void setAttribute( TorrentAttribute attribute, String value )579 setAttribute( 580 TorrentAttribute attribute, 581 String value ) 582 { 583 String name = convertAttribute( attribute ); 584 585 if ( name != null ){ 586 587 download_manager.getDownloadState().setAttribute( name, value ); 588 } 589 } 590 hasAttribute(TorrentAttribute attribute)591 public boolean hasAttribute(TorrentAttribute attribute) { 592 String name = convertAttribute(attribute); 593 if (name == null) {return false;} 594 return download_manager.getDownloadState().hasAttribute(name); 595 } 596 getBooleanAttribute(TorrentAttribute attribute)597 public boolean getBooleanAttribute(TorrentAttribute attribute) { 598 String name = convertAttribute(attribute); 599 if (name == null) {return false;} // Default value 600 return download_manager.getDownloadState().getBooleanAttribute(name); 601 } 602 setBooleanAttribute(TorrentAttribute attribute, boolean value)603 public void setBooleanAttribute(TorrentAttribute attribute, boolean value) { 604 String name = convertAttribute(attribute); 605 if (name != null) { 606 download_manager.getDownloadState().setBooleanAttribute(name, value); 607 } 608 } 609 getIntAttribute(TorrentAttribute attribute)610 public int getIntAttribute(TorrentAttribute attribute) { 611 String name = convertAttribute(attribute); 612 if (name == null) {return 0;} // Default value 613 return download_manager.getDownloadState().getIntAttribute(name); 614 } 615 setIntAttribute(TorrentAttribute attribute, int value)616 public void setIntAttribute(TorrentAttribute attribute, int value) { 617 String name = convertAttribute(attribute); 618 if (name != null) { 619 download_manager.getDownloadState().setIntAttribute(name, value); 620 } 621 } 622 getLongAttribute(TorrentAttribute attribute)623 public long getLongAttribute(TorrentAttribute attribute) { 624 String name = convertAttribute(attribute); 625 if (name == null) {return 0L;} // Default value 626 return download_manager.getDownloadState().getLongAttribute(name); 627 } 628 setLongAttribute(TorrentAttribute attribute, long value)629 public void setLongAttribute(TorrentAttribute attribute, long value) { 630 String name = convertAttribute(attribute); 631 if (name != null) { 632 download_manager.getDownloadState().setLongAttribute(name, value); 633 } 634 } 635 636 protected String convertAttribute( TorrentAttribute attribute )637 convertAttribute( 638 TorrentAttribute attribute ) 639 { 640 if ( attribute.getName() == TorrentAttribute.TA_CATEGORY ){ 641 642 return( DownloadManagerState.AT_CATEGORY ); 643 644 }else if ( attribute.getName() == TorrentAttribute.TA_NETWORKS ){ 645 646 return( DownloadManagerState.AT_NETWORKS ); 647 648 }else if ( attribute.getName() == TorrentAttribute.TA_TRACKER_CLIENT_EXTENSIONS ){ 649 650 return( DownloadManagerState.AT_TRACKER_CLIENT_EXTENSIONS ); 651 652 }else if ( attribute.getName() == TorrentAttribute.TA_PEER_SOURCES ){ 653 654 return( DownloadManagerState.AT_PEER_SOURCES ); 655 656 }else if ( attribute.getName() == TorrentAttribute.TA_DISPLAY_NAME ){ 657 658 return( DownloadManagerState.AT_DISPLAY_NAME ); 659 660 }else if ( attribute.getName() == TorrentAttribute.TA_USER_COMMENT ){ 661 662 return( DownloadManagerState.AT_USER_COMMENT ); 663 664 }else if ( attribute.getName() == TorrentAttribute.TA_RELATIVE_SAVE_PATH ){ 665 666 return( DownloadManagerState.AT_RELATIVE_SAVE_PATH ); 667 668 }else if ( attribute.getName() == TorrentAttribute.TA_SHARE_PROPERTIES ){ 669 670 // this is a share-level attribute only, not propagated to individual downloads 671 672 return( null ); 673 674 }else if ( attribute.getName().startsWith( "Plugin." )){ 675 676 return( attribute.getName()); 677 678 }else{ 679 680 Debug.out( "Can't convert attribute '" + attribute.getName() + "'" ); 681 682 return( null ); 683 } 684 } 685 686 protected TorrentAttribute convertAttribute( String name )687 convertAttribute( 688 String name ) 689 { 690 if ( name.equals( DownloadManagerState.AT_CATEGORY )){ 691 692 return( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_CATEGORY )); 693 694 }else if ( name.equals( DownloadManagerState.AT_NETWORKS )){ 695 696 return( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_NETWORKS )); 697 698 }else if ( name.equals( DownloadManagerState.AT_PEER_SOURCES )){ 699 700 return( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_PEER_SOURCES )); 701 702 }else if ( name.equals( DownloadManagerState.AT_TRACKER_CLIENT_EXTENSIONS )){ 703 704 return( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_TRACKER_CLIENT_EXTENSIONS )); 705 706 }else if ( name.equals ( DownloadManagerState.AT_DISPLAY_NAME)){ 707 708 return ( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_DISPLAY_NAME )); 709 710 }else if ( name.equals ( DownloadManagerState.AT_USER_COMMENT)){ 711 712 return ( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_USER_COMMENT )); 713 714 }else if ( name.equals ( DownloadManagerState.AT_RELATIVE_SAVE_PATH)){ 715 716 return ( TorrentManagerImpl.getSingleton().getAttribute( TorrentAttribute.TA_RELATIVE_SAVE_PATH )); 717 718 }else if ( name.startsWith( "Plugin." )){ 719 720 return( TorrentManagerImpl.getSingleton().getAttribute( name )); 721 722 }else{ 723 724 return( null ); 725 } 726 } 727 setCategory(String sName)728 public void setCategory(String sName) { 729 Category category = CategoryManager.getCategory(sName); 730 if (category == null) 731 category = CategoryManager.createCategory(sName); 732 download_manager.getDownloadState().setCategory(category); 733 } 734 isPersistent()735 public boolean isPersistent() { 736 return download_manager.isPersistent(); 737 } 738 739 public void remove()740 remove() 741 742 throws DownloadException, DownloadRemovalVetoException 743 { 744 remove( false, false ); 745 } 746 747 public void remove( boolean delete_torrent, boolean delete_data )748 remove( 749 boolean delete_torrent, 750 boolean delete_data ) 751 752 throws DownloadException, DownloadRemovalVetoException 753 { 754 int dl_state = download_manager.getState(); 755 756 if ( dl_state == DownloadManager.STATE_STOPPED || 757 dl_state == DownloadManager.STATE_ERROR || 758 dl_state == DownloadManager.STATE_QUEUED ){ 759 760 GlobalManager globalManager = download_manager.getGlobalManager(); 761 762 try{ 763 764 globalManager.removeDownloadManager(download_manager, delete_torrent, delete_data); 765 766 }catch( GlobalManagerDownloadRemovalVetoException e ){ 767 768 throw( new DownloadRemovalVetoException( e.getMessage())); 769 } 770 771 }else{ 772 773 throw( new DownloadRemovalVetoException( MessageText.getString("plugin.download.remove.veto.notstopped"))); 774 } 775 } 776 777 public boolean canBeRemoved()778 canBeRemoved() 779 780 throws DownloadRemovalVetoException 781 { 782 int dl_state = download_manager.getState(); 783 784 if ( dl_state == DownloadManager.STATE_STOPPED || 785 dl_state == DownloadManager.STATE_ERROR || 786 dl_state == DownloadManager.STATE_QUEUED ){ 787 788 GlobalManager globalManager = download_manager.getGlobalManager(); 789 790 try{ 791 globalManager.canDownloadManagerBeRemoved(download_manager, false, false); 792 793 }catch( GlobalManagerDownloadRemovalVetoException e ){ 794 795 throw( new DownloadRemovalVetoException( e.getMessage(),e.isSilent())); 796 } 797 798 }else{ 799 800 throw( new DownloadRemovalVetoException( MessageText.getString("plugin.download.remove.veto.notstopped"))); 801 } 802 803 return( true ); 804 } 805 806 public DownloadStats getStats()807 getStats() 808 { 809 return( download_stats ); 810 } 811 812 public boolean isComplete()813 isComplete() 814 { 815 return download_manager.isDownloadComplete(false); 816 } 817 isComplete(boolean bIncludeDND)818 public boolean isComplete(boolean bIncludeDND) { 819 return download_manager.isDownloadComplete(bIncludeDND); 820 } 821 822 public boolean isChecking()823 isChecking() 824 { 825 return( download_stats.getCheckingDoneInThousandNotation() != -1 ); 826 } 827 828 public boolean isMoving()829 isMoving() 830 { 831 org.gudy.azureus2.core3.disk.DiskManager dm = download_manager.getDiskManager(); 832 833 if ( dm != null ){ 834 835 return( dm.getMoveProgress() != -1 ); 836 } 837 838 return( false ); 839 } 840 841 protected void isRemovable()842 isRemovable() 843 throws DownloadRemovalVetoException 844 { 845 // no sync required, see update code 846 847 for (int i=0;i<removal_listeners.size();i++){ 848 849 try{ 850 ((DownloadWillBeRemovedListener)removal_listeners.get(i)).downloadWillBeRemoved(this); 851 852 }catch( DownloadRemovalVetoException e ){ 853 854 throw( e ); 855 856 }catch( Throwable e ){ 857 858 Debug.printStackTrace( e ); 859 } 860 } 861 } 862 863 protected void destroy()864 destroy() 865 { 866 download_manager.removeListener( this ); 867 } 868 869 870 // DownloadManagerListener methods 871 872 public void stateChanged( DownloadManager manager, int state )873 stateChanged( 874 DownloadManager manager, 875 int state ) 876 { 877 int prev_state = latest_state; 878 879 latest_state = convertState(state); 880 881 // System.out.println("Plug: dl = " + getName() + ", prev = " + prev_state + ", curr = " + latest_state + ", signalled state = " + state); 882 883 boolean curr_forcedStart = isForceStart(); 884 885 // Copy reference in case any attempts to remove or add listeners are tried. 886 List listeners_to_use = listeners; 887 888 if ( prev_state != latest_state || latest_forcedStart != curr_forcedStart ){ 889 890 latest_forcedStart = curr_forcedStart; 891 892 for (int i=0;i<listeners_to_use.size();i++){ 893 894 try{ 895 long startTime = SystemTime.getCurrentTime(); 896 DownloadListener listener = (DownloadListener)listeners_to_use.get(i); 897 898 listener.stateChanged( this, prev_state, latest_state ); 899 900 long diff = SystemTime.getCurrentTime() - startTime; 901 if (diff > 1000) { 902 System.out.println("Plugin should move long processes (" + diff 903 + "ms) off of Download's stateChanged listener trigger. " 904 + listener); 905 } 906 907 }catch( Throwable e ){ 908 909 Debug.printStackTrace( e ); 910 } 911 } 912 } 913 } 914 915 public void downloadComplete(DownloadManager manager)916 downloadComplete(DownloadManager manager) 917 { 918 if (this.completion_listeners.isEmpty()) {return;} 919 Iterator itr = this.completion_listeners.iterator(); 920 DownloadCompletionListener dcl; 921 while (itr.hasNext()) { 922 dcl = (DownloadCompletionListener)itr.next(); 923 long startTime = SystemTime.getCurrentTime(); 924 try {dcl.onCompletion(this);} 925 catch (Throwable t) {Debug.printStackTrace(t);} 926 long diff = SystemTime.getCurrentTime() - startTime; 927 if (diff > 1000) { 928 System.out.println("Plugin should move long processes (" + diff + "ms) off of Download's onCompletion listener trigger. " + dcl); 929 } 930 } 931 } 932 933 public void completionChanged( DownloadManager manager, boolean bCompleted)934 completionChanged( 935 DownloadManager manager, 936 boolean bCompleted) 937 { 938 } 939 940 public void filePriorityChanged( DownloadManager download, org.gudy.azureus2.core3.disk.DiskManagerFileInfo file )941 filePriorityChanged( DownloadManager download, org.gudy.azureus2.core3.disk.DiskManagerFileInfo file ) 942 { 943 } 944 945 public void positionChanged( DownloadManager download, int oldPosition, int newPosition)946 positionChanged( 947 DownloadManager download, 948 int oldPosition, 949 int newPosition) 950 { 951 for (int i = 0; i < listeners.size(); i++) { 952 try { 953 long startTime = SystemTime.getCurrentTime(); 954 DownloadListener listener = (DownloadListener)listeners.get(i); 955 956 listener.positionChanged(this, oldPosition, newPosition); 957 958 long diff = SystemTime.getCurrentTime() - startTime; 959 if (diff > 1000) { 960 System.out.println("Plugin should move long processes (" + diff 961 + "ms) off of Download's positionChanged listener trigger. " 962 + listener); 963 } 964 } catch (Throwable e) { 965 Debug.printStackTrace( e ); 966 } 967 } 968 } 969 970 public void addListener( DownloadListener l )971 addListener( 972 DownloadListener l ) 973 { 974 try{ 975 listeners_mon.enter(); 976 977 List new_listeners = new ArrayList( listeners ); 978 979 new_listeners.add(l); 980 981 listeners = new_listeners; 982 }finally{ 983 984 listeners_mon.exit(); 985 } 986 } 987 988 989 public void removeListener( DownloadListener l )990 removeListener( 991 DownloadListener l ) 992 { 993 try{ 994 listeners_mon.enter(); 995 996 List new_listeners = new ArrayList(listeners); 997 998 new_listeners.remove(l); 999 1000 listeners = new_listeners; 1001 }finally{ 1002 1003 listeners_mon.exit(); 1004 } 1005 } 1006 addAttributeListener(DownloadAttributeListener listener, TorrentAttribute attr, int event_type)1007 public void addAttributeListener(DownloadAttributeListener listener, TorrentAttribute attr, int event_type) { 1008 String attribute = convertAttribute(attr); 1009 if (attribute == null) {return;} 1010 1011 CopyOnWriteMap attr_map = this.getAttributeMapForType(event_type); 1012 CopyOnWriteList listener_list = (CopyOnWriteList)attr_map.get(attribute); 1013 boolean add_self = false; 1014 1015 if (listener_list == null) { 1016 listener_list = new CopyOnWriteList(); 1017 attr_map.put(attribute, listener_list); 1018 } 1019 add_self = listener_list.isEmpty(); 1020 1021 listener_list.add(listener); 1022 if (add_self) { 1023 download_manager.getDownloadState().addListener(this, attribute, event_type); 1024 } 1025 } 1026 removeAttributeListener(DownloadAttributeListener listener, TorrentAttribute attr, int event_type)1027 public void removeAttributeListener(DownloadAttributeListener listener, TorrentAttribute attr, int event_type) { 1028 String attribute = convertAttribute(attr); 1029 if (attribute == null) {return;} 1030 1031 CopyOnWriteMap attr_map = this.getAttributeMapForType(event_type); 1032 CopyOnWriteList listener_list = (CopyOnWriteList)attr_map.get(attribute); 1033 boolean remove_self = false; 1034 1035 if (listener_list != null) { 1036 listener_list.remove(listener); 1037 remove_self = listener_list.isEmpty(); 1038 } 1039 1040 if (remove_self) { 1041 download_manager.getDownloadState().removeListener(this, attribute, event_type); 1042 } 1043 1044 } 1045 1046 public DownloadAnnounceResult getLastAnnounceResult()1047 getLastAnnounceResult() 1048 { 1049 TRTrackerAnnouncer tc = download_manager.getTrackerClient(); 1050 1051 if ( tc != null ){ 1052 1053 last_announce_result.setContent( tc.getLastResponse()); 1054 } 1055 1056 return( last_announce_result ); 1057 } 1058 1059 public DownloadScrapeResult getLastScrapeResult()1060 getLastScrapeResult() 1061 { 1062 TRTrackerScraperResponse response = download_manager.getTrackerScrapeResponse(); 1063 1064 if ( response != null ){ 1065 1066 // don't notify plugins of intermediate (initializing, scraping) states as they would be picked up as errors 1067 1068 if ( response.getStatus() == TRTrackerScraperResponse.ST_ERROR || response.getStatus() == TRTrackerScraperResponse.ST_ONLINE ){ 1069 1070 last_scrape_result.setContent( response ); 1071 } 1072 } 1073 1074 return( last_scrape_result ); 1075 } 1076 1077 public DownloadScrapeResult getAggregatedScrapeResult()1078 getAggregatedScrapeResult() 1079 { 1080 DownloadScrapeResult result = getAggregatedScrapeResultSupport(); 1081 1082 if ( result != null ){ 1083 1084 String cache = download_manager.getDownloadState().getAttribute( DownloadManagerState.AT_AGGREGATE_SCRAPE_CACHE ); 1085 1086 boolean do_update = true; 1087 1088 long mins = SystemTime.getCurrentTime()/(1000*60); 1089 1090 if ( cache != null ){ 1091 1092 String[] bits = cache.split(","); 1093 1094 if ( bits.length == 3 ){ 1095 1096 long updated_mins = 0; 1097 1098 try{ 1099 updated_mins = Long.parseLong( bits[0] ); 1100 1101 }catch( Throwable e ){ 1102 1103 } 1104 1105 if ( mins - updated_mins < 15 ){ 1106 1107 1108 do_update = false; 1109 } 1110 } 1111 } 1112 1113 if ( do_update ){ 1114 1115 String str = mins + "," + result.getSeedCount() + "," + result.getNonSeedCount(); 1116 1117 download_manager.getDownloadState().setAttribute( DownloadManagerState.AT_AGGREGATE_SCRAPE_CACHE, str ); 1118 } 1119 } 1120 1121 return( result ); 1122 } 1123 1124 private DownloadScrapeResult getAggregatedScrapeResultSupport()1125 getAggregatedScrapeResultSupport() 1126 { 1127 List<TRTrackerScraperResponse> responses = download_manager.getGoodTrackerScrapeResponses(); 1128 1129 int best_peers = -1; 1130 int best_seeds = -1; 1131 int best_time = -1; 1132 1133 TRTrackerScraperResponse best_resp = null; 1134 1135 if ( responses != null ){ 1136 1137 for ( TRTrackerScraperResponse response: responses ){ 1138 1139 int peers = response.getPeers(); 1140 int seeds = response.getSeeds(); 1141 1142 if ( peers > best_peers || 1143 ( peers == best_peers && seeds > best_seeds )){ 1144 1145 best_peers = peers; 1146 best_seeds = seeds; 1147 1148 best_resp = response; 1149 } 1150 } 1151 } 1152 1153 // if no good real tracker responses then use less reliable DHT ones 1154 1155 if ( best_peers == -1 ){ 1156 1157 try{ 1158 TrackerPeerSource our_dht = null; 1159 1160 List<TrackerPeerSource> peer_sources = download_manager.getTrackerPeerSources(); 1161 1162 for ( TrackerPeerSource ps: peer_sources ){ 1163 1164 if ( ps.getType() == TrackerPeerSource.TP_DHT ){ 1165 1166 our_dht = ps; 1167 1168 break; 1169 } 1170 } 1171 1172 peer_listeners_mon.enter(); 1173 1174 if ( announce_response_map != null ){ 1175 1176 int total_seeds = 0; 1177 int total_peers = 0; 1178 int latest_time = 0; 1179 1180 int num = 0; 1181 1182 if ( our_dht != null && our_dht.getStatus() == TrackerPeerSource.ST_ONLINE ){ 1183 1184 total_seeds = our_dht.getSeedCount(); 1185 total_peers = our_dht.getLeecherCount(); 1186 latest_time = our_dht.getLastUpdate(); 1187 1188 num = 1; 1189 } 1190 1191 for ( int[] entry: announce_response_map.values()){ 1192 1193 num++; 1194 1195 int seeds = entry[0]; 1196 int peers = entry[1]; 1197 int time = entry[3]; 1198 1199 total_seeds += seeds; 1200 total_peers += peers; 1201 1202 if ( time > latest_time ){ 1203 1204 latest_time = time; 1205 } 1206 } 1207 1208 if ( total_peers >= 0 ){ 1209 1210 best_peers = Math.max( 1, total_peers / num ); 1211 best_seeds = total_seeds / num; 1212 1213 if ( total_seeds > 0 && best_seeds == 0 ){ 1214 1215 best_seeds = 1; 1216 } 1217 best_time = latest_time; 1218 best_resp = null; 1219 } 1220 } 1221 1222 }finally{ 1223 1224 peer_listeners_mon.exit(); 1225 } 1226 } 1227 1228 if ( best_peers >= 0 ){ 1229 1230 // System.out.println( download_manager.getDisplayName() + ": " + best_peers + "/" + best_seeds + "/" + best_resp ); 1231 1232 last_aggregate_scrape.update( best_resp, best_seeds, best_peers, best_time ); 1233 1234 return( last_aggregate_scrape ); 1235 1236 }else{ 1237 1238 return( getLastScrapeResult()); 1239 } 1240 } 1241 1242 public void scrapeResult( TRTrackerScraperResponse response )1243 scrapeResult( 1244 TRTrackerScraperResponse response ) 1245 { 1246 // don't notify plugins of intermediate (initializing, scraping) states as they would be picked up as errors 1247 if(response.getStatus() != TRTrackerScraperResponse.ST_ERROR && response.getStatus() != TRTrackerScraperResponse.ST_ONLINE) 1248 return; 1249 1250 last_scrape_result.setContent( response ); 1251 1252 for (int i=0;i<tracker_listeners.size();i++){ 1253 1254 try{ 1255 ((DownloadTrackerListener)tracker_listeners.get(i)).scrapeResult( last_scrape_result ); 1256 1257 }catch( Throwable e ){ 1258 1259 Debug.printStackTrace( e ); 1260 } 1261 } 1262 } 1263 1264 // Used by DownloadEventNotifierImpl. announceTrackerResultsToListener(DownloadTrackerListener l)1265 void announceTrackerResultsToListener(DownloadTrackerListener l) { 1266 l.announceResult(last_announce_result); 1267 l.scrapeResult(last_scrape_result); 1268 } 1269 1270 public void announceResult( TRTrackerAnnouncerResponse response )1271 announceResult( 1272 TRTrackerAnnouncerResponse response ) 1273 { 1274 last_announce_result.setContent( response ); 1275 1276 List tracker_listeners_ref = tracker_listeners; 1277 1278 for (int i=0;i<tracker_listeners_ref.size();i++){ 1279 1280 try{ 1281 ((DownloadTrackerListener)tracker_listeners_ref.get(i)).announceResult( last_announce_result ); 1282 1283 }catch( Throwable e ){ 1284 1285 Debug.printStackTrace( e ); 1286 } 1287 } 1288 } 1289 1290 public TrackerPeerSource getTrackerPeerSource()1291 getTrackerPeerSource() 1292 { 1293 return( 1294 new TrackerPeerSourceAdapter() 1295 { 1296 private long fixup; 1297 private int state; 1298 private String details = ""; 1299 private int seeds; 1300 private int leechers; 1301 private int peers; 1302 1303 private void 1304 fixup() 1305 { 1306 long now = SystemTime.getCurrentTime(); 1307 1308 if ( now - fixup > 1000 ){ 1309 1310 if ( !download_manager.getDownloadState().isPeerSourceEnabled( PEPeerSource.PS_PLUGIN )){ 1311 1312 state = ST_DISABLED; 1313 1314 }else{ 1315 1316 int s = getState(); 1317 1318 if ( s == ST_DOWNLOADING || s == ST_SEEDING ){ 1319 1320 state = ST_ONLINE; 1321 1322 }else{ 1323 1324 state = ST_STOPPED; 1325 } 1326 } 1327 1328 if ( state == ST_ONLINE ){ 1329 1330 try{ 1331 peer_listeners_mon.enter(); 1332 1333 int s = 0; 1334 int l = 0; 1335 int p = 0; 1336 1337 String str = ""; 1338 1339 if ( announce_response_map != null ){ 1340 1341 for (Map.Entry<String, int[]> entry: announce_response_map.entrySet()){ 1342 1343 String cn = entry.getKey(); 1344 int[] data = entry.getValue(); 1345 1346 str += (str.length()==0?"":", ") + cn; 1347 1348 str += " " + data[0] + "/" + data[1] + "/" + data[2]; 1349 1350 s += data[0]; 1351 l += data[1]; 1352 p += data[2]; 1353 } 1354 } 1355 1356 details = str; 1357 1358 if ( str.length() == 0 ){ 1359 1360 seeds = -1; 1361 leechers = -1; 1362 peers = -1; 1363 1364 }else{ 1365 1366 seeds = s; 1367 leechers = l; 1368 peers = p; 1369 } 1370 1371 }finally{ 1372 1373 peer_listeners_mon.exit(); 1374 } 1375 }else{ 1376 1377 details = ""; 1378 } 1379 1380 fixup = now; 1381 } 1382 } 1383 1384 public int 1385 getType() 1386 { 1387 return( TP_PLUGIN ); 1388 } 1389 1390 public int 1391 getStatus() 1392 { 1393 fixup(); 1394 1395 return( state ); 1396 } 1397 1398 public String 1399 getName() 1400 { 1401 fixup(); 1402 1403 if ( state == ST_ONLINE ){ 1404 1405 return( details ); 1406 } 1407 1408 return( "" ); 1409 } 1410 1411 public int 1412 getSeedCount() 1413 { 1414 fixup(); 1415 1416 if ( state == ST_ONLINE ){ 1417 1418 return( seeds ); 1419 } 1420 1421 return( -1 ); 1422 } 1423 1424 public int 1425 getLeecherCount() 1426 { 1427 fixup(); 1428 1429 if ( state == ST_ONLINE ){ 1430 1431 return( leechers ); 1432 } 1433 1434 return( -1 ); 1435 } 1436 1437 public int 1438 getPeers() 1439 { 1440 fixup(); 1441 1442 if ( state == ST_ONLINE ){ 1443 1444 return( peers ); 1445 } 1446 1447 return( -1 ); 1448 } 1449 }); 1450 } 1451 1452 private String getTrackingName( Object obj )1453 getTrackingName( 1454 Object obj ) 1455 { 1456 String name = obj.getClass().getName(); 1457 1458 int pos = name.lastIndexOf( '.' ); 1459 1460 name = name.substring( pos+1 ); 1461 1462 pos = name.indexOf( '$' ); 1463 1464 if ( pos != -1 ){ 1465 1466 name = name.substring( 0, pos ); 1467 } 1468 1469 // hack alert - could use classloader to find plugin I guess 1470 1471 pos = name.indexOf( "DHTTrackerPlugin" ); 1472 1473 if ( pos == 0 ){ 1474 1475 // built in 1476 1477 name = null; 1478 1479 }else if ( pos > 0 ){ 1480 1481 name = name.substring( 0, pos ); 1482 1483 }else if ( name.equals( "DHTAnnounceResult")){ 1484 1485 name = "mlDHT"; 1486 } 1487 1488 return( name ); 1489 } 1490 1491 public void setAnnounceResult( DownloadAnnounceResult result )1492 setAnnounceResult( 1493 DownloadAnnounceResult result ) 1494 { 1495 String class_name = getTrackingName( result ); 1496 1497 if ( class_name != null ){ 1498 1499 int seeds = result.getSeedCount(); 1500 int leechers = result.getNonSeedCount(); 1501 1502 DownloadAnnounceResultPeer[] peers = result.getPeers(); 1503 1504 int peer_count = peers==null?0:peers.length; 1505 1506 try{ 1507 peer_listeners_mon.enter(); 1508 1509 if ( announce_response_map == null ){ 1510 1511 announce_response_map = new HashMap<String, int[]>(); 1512 1513 }else{ 1514 1515 if ( announce_response_map.size() > 32 ){ 1516 1517 Debug.out( "eh?" ); 1518 1519 announce_response_map.clear(); 1520 } 1521 } 1522 1523 int[] data = (int[])announce_response_map.get( class_name ); 1524 1525 if ( data == null ){ 1526 1527 data = new int[4]; 1528 1529 announce_response_map.put( class_name, data ); 1530 } 1531 1532 data[0] = seeds; 1533 data[1] = leechers; 1534 data[2] = peer_count; 1535 data[3] = (int)(SystemTime.getCurrentTime()/1000); 1536 1537 }finally{ 1538 1539 peer_listeners_mon.exit(); 1540 } 1541 } 1542 1543 download_manager.setAnnounceResult( result ); 1544 } 1545 1546 public void setScrapeResult( DownloadScrapeResult result )1547 setScrapeResult( 1548 DownloadScrapeResult result ) 1549 { 1550 String class_name = getTrackingName( result ); 1551 1552 if ( class_name != null ){ 1553 1554 int seeds = result.getSeedCount(); 1555 int leechers = result.getNonSeedCount(); 1556 1557 try{ 1558 peer_listeners_mon.enter(); 1559 1560 if ( announce_response_map == null ){ 1561 1562 announce_response_map = new HashMap<String, int[]>(); 1563 1564 }else{ 1565 1566 if ( announce_response_map.size() > 32 ){ 1567 1568 Debug.out( "eh?" ); 1569 1570 announce_response_map.clear(); 1571 } 1572 } 1573 1574 int[] data = (int[])announce_response_map.get( class_name ); 1575 1576 if ( data == null ){ 1577 1578 data = new int[4]; 1579 1580 announce_response_map.put( class_name, data ); 1581 } 1582 1583 data[0] = seeds; 1584 data[1] = leechers; 1585 data[3] = (int)(SystemTime.getCurrentTime()/1000); 1586 }finally{ 1587 1588 peer_listeners_mon.exit(); 1589 } 1590 } 1591 1592 download_manager.setScrapeResult( result ); 1593 } 1594 1595 public void stateChanged( DownloadManagerState state, DownloadManagerStateEvent event )1596 stateChanged( 1597 DownloadManagerState state, 1598 DownloadManagerStateEvent event ) 1599 { 1600 final int type = event.getType(); 1601 1602 if ( type == DownloadManagerStateEvent.ET_ATTRIBUTE_WRITTEN || 1603 type == DownloadManagerStateEvent.ET_ATTRIBUTE_WILL_BE_READ ){ 1604 1605 String name = (String)event.getData(); 1606 1607 List property_listeners_ref = property_listeners; 1608 1609 final TorrentAttribute attr = convertAttribute( name ); 1610 1611 if ( attr != null ){ 1612 1613 for (int i=0;i<property_listeners_ref.size();i++){ 1614 1615 try{ 1616 ((DownloadPropertyListener)property_listeners_ref.get(i)).propertyChanged( 1617 this, 1618 new DownloadPropertyEvent() 1619 { 1620 public int 1621 getType() 1622 { 1623 return( type==DownloadManagerStateEvent.ET_ATTRIBUTE_WRITTEN 1624 ?DownloadPropertyEvent.PT_TORRENT_ATTRIBUTE_WRITTEN 1625 :DownloadPropertyEvent.PT_TORRENT_ATTRIBUTE_WILL_BE_READ ); 1626 } 1627 1628 public Object 1629 getData() 1630 { 1631 return( attr ); 1632 } 1633 }); 1634 1635 }catch( Throwable e ){ 1636 1637 Debug.printStackTrace( e ); 1638 } 1639 } 1640 } 1641 } 1642 } 1643 1644 public void addPropertyListener( DownloadPropertyListener l )1645 addPropertyListener( 1646 DownloadPropertyListener l ) 1647 { 1648 1649 // Compatibility for the autostop plugin. 1650 if ("com.aimedia.stopseeding.core.RatioWatcher".equals(l.getClass().getName())) { 1651 1652 // Looking at the source code, this method doesn't actually appear to do anything, 1653 // so we can avoid doing anything for now. 1654 return; 1655 /* 1656 if (property_to_attribute_map == null) {property_to_attribute_map = new HashMap(1);} 1657 DownloadAttributeListener dal = new PropertyListenerBridge(l); 1658 property_to_attribute_map.put(l, dal); 1659 this.addAttributeListener(dal, attr, event_type); 1660 */ 1661 } 1662 1663 PluginDeprecation.call("property listener", l); 1664 try{ 1665 tracker_listeners_mon.enter(); 1666 1667 List new_property_listeners = new ArrayList( property_listeners ); 1668 1669 new_property_listeners.add( l ); 1670 1671 property_listeners = new_property_listeners; 1672 1673 if ( property_listeners.size() == 1 ){ 1674 1675 download_manager.getDownloadState().addListener( this ); 1676 } 1677 }finally{ 1678 1679 tracker_listeners_mon.exit(); 1680 } 1681 } 1682 1683 public void removePropertyListener( DownloadPropertyListener l )1684 removePropertyListener( 1685 DownloadPropertyListener l ) 1686 { 1687 1688 // Compatibility for the autostop plugin. 1689 if ("com.aimedia.stopseeding.core.RatioWatcher".equals(l.getClass().getName())) { 1690 1691 // Looking at the source code, this method doesn't actually appear to do anything, 1692 // so we can avoid doing anything for now. 1693 return; 1694 } 1695 1696 try{ 1697 tracker_listeners_mon.enter(); 1698 1699 List new_property_listeners = new ArrayList( property_listeners ); 1700 1701 new_property_listeners.remove( l ); 1702 1703 property_listeners = new_property_listeners; 1704 1705 if ( property_listeners.size() == 0 ){ 1706 1707 download_manager.getDownloadState().removeListener( this ); 1708 } 1709 }finally{ 1710 1711 tracker_listeners_mon.exit(); 1712 } 1713 } 1714 1715 public void torrentChanged()1716 torrentChanged() 1717 { 1718 TRTrackerAnnouncer client = download_manager.getTrackerClient(); 1719 1720 if ( client != null ){ 1721 1722 client.resetTrackerUrl(true); 1723 } 1724 } 1725 1726 public void addTrackerListener( DownloadTrackerListener l )1727 addTrackerListener( 1728 DownloadTrackerListener l ) 1729 { 1730 addTrackerListener(l, true); 1731 } 1732 1733 public void addTrackerListener( DownloadTrackerListener l, boolean immediateTrigger )1734 addTrackerListener( 1735 DownloadTrackerListener l, 1736 boolean immediateTrigger ) 1737 { 1738 try{ 1739 tracker_listeners_mon.enter(); 1740 1741 List new_tracker_listeners = new ArrayList( tracker_listeners ); 1742 1743 new_tracker_listeners.add( l ); 1744 1745 tracker_listeners = new_tracker_listeners; 1746 1747 if ( tracker_listeners.size() == 1 ){ 1748 1749 download_manager.addTrackerListener( this ); 1750 } 1751 }finally{ 1752 1753 tracker_listeners_mon.exit(); 1754 } 1755 1756 if (immediateTrigger) {this.announceTrackerResultsToListener(l);} 1757 } 1758 1759 public void removeTrackerListener( DownloadTrackerListener l )1760 removeTrackerListener( 1761 DownloadTrackerListener l ) 1762 { 1763 try{ 1764 tracker_listeners_mon.enter(); 1765 1766 List new_tracker_listeners = new ArrayList( tracker_listeners ); 1767 1768 new_tracker_listeners.remove( l ); 1769 1770 tracker_listeners = new_tracker_listeners; 1771 1772 if ( tracker_listeners.size() == 0 ){ 1773 1774 download_manager.removeTrackerListener( this ); 1775 } 1776 }finally{ 1777 1778 tracker_listeners_mon.exit(); 1779 } 1780 } 1781 1782 public void addDownloadWillBeRemovedListener( DownloadWillBeRemovedListener l )1783 addDownloadWillBeRemovedListener( 1784 DownloadWillBeRemovedListener l ) 1785 { 1786 try{ 1787 removal_listeners_mon.enter(); 1788 1789 List new_removal_listeners = new ArrayList( removal_listeners ); 1790 1791 new_removal_listeners.add(l); 1792 1793 removal_listeners = new_removal_listeners; 1794 1795 }finally{ 1796 1797 removal_listeners_mon.exit(); 1798 } 1799 } 1800 1801 public void removeDownloadWillBeRemovedListener( DownloadWillBeRemovedListener l )1802 removeDownloadWillBeRemovedListener( 1803 DownloadWillBeRemovedListener l ) 1804 { 1805 try{ 1806 removal_listeners_mon.enter(); 1807 1808 List new_removal_listeners = new ArrayList( removal_listeners ); 1809 1810 new_removal_listeners.remove(l); 1811 1812 removal_listeners = new_removal_listeners; 1813 1814 }finally{ 1815 1816 removal_listeners_mon.exit(); 1817 } 1818 } 1819 1820 public void addPeerListener( final DownloadPeerListener listener )1821 addPeerListener( 1822 final DownloadPeerListener listener ) 1823 { 1824 DownloadManagerPeerListener delegate = 1825 new DownloadManagerPeerListener() 1826 { 1827 1828 public void 1829 peerManagerAdded( 1830 PEPeerManager manager ) 1831 { 1832 PeerManager pm = PeerManagerImpl.getPeerManager( manager); 1833 1834 listener.peerManagerAdded( DownloadImpl.this, pm ); 1835 } 1836 1837 public void 1838 peerManagerRemoved( 1839 PEPeerManager manager ) 1840 { 1841 PeerManager pm = PeerManagerImpl.getPeerManager( manager); 1842 1843 listener.peerManagerRemoved( DownloadImpl.this, pm ); 1844 1845 } 1846 1847 public void 1848 peerManagerWillBeAdded( 1849 PEPeerManager manager ) 1850 { 1851 } 1852 1853 public void 1854 peerAdded( 1855 PEPeer peer ) 1856 { 1857 } 1858 1859 public void 1860 peerRemoved( 1861 PEPeer peer ) 1862 { 1863 } 1864 }; 1865 1866 try{ 1867 peer_listeners_mon.enter(); 1868 1869 peer_listeners.put( listener, delegate ); 1870 1871 }finally{ 1872 1873 peer_listeners_mon.exit(); 1874 } 1875 1876 download_manager.addPeerListener( delegate ); 1877 } 1878 1879 1880 public void removePeerListener( DownloadPeerListener listener )1881 removePeerListener( 1882 DownloadPeerListener listener ) 1883 { 1884 DownloadManagerPeerListener delegate; 1885 1886 try{ 1887 peer_listeners_mon.enter(); 1888 1889 delegate = (DownloadManagerPeerListener)peer_listeners.remove( listener ); 1890 1891 }finally{ 1892 1893 peer_listeners_mon.exit(); 1894 } 1895 1896 if ( delegate == null ){ 1897 1898 // sometimes we end up with double removal so don't bother spewing about this 1899 // Debug.out( "Listener not found for removal" ); 1900 1901 }else{ 1902 1903 download_manager.removePeerListener( delegate ); 1904 } 1905 } 1906 1907 public boolean activateRequest( final int count )1908 activateRequest( 1909 final int count ) 1910 { 1911 DownloadActivationEvent event = 1912 new DownloadActivationEvent() 1913 { 1914 public Download 1915 getDownload() 1916 { 1917 return( DownloadImpl.this ); 1918 } 1919 1920 public int 1921 getActivationCount() 1922 { 1923 return( count ); 1924 } 1925 }; 1926 1927 for (Iterator it=activation_listeners.iterator();it.hasNext();){ 1928 1929 try{ 1930 DownloadActivationListener listener = (DownloadActivationListener)it.next(); 1931 1932 if ( listener.activationRequested( event )){ 1933 1934 return( true ); 1935 } 1936 }catch( Throwable e ){ 1937 1938 Debug.printStackTrace(e); 1939 } 1940 } 1941 1942 return( false ); 1943 } 1944 1945 public DownloadActivationEvent getActivationState()1946 getActivationState() 1947 { 1948 return( activation_state ); 1949 } 1950 1951 public void addActivationListener( DownloadActivationListener l )1952 addActivationListener( 1953 DownloadActivationListener l ) 1954 { 1955 try{ 1956 peer_listeners_mon.enter(); 1957 1958 activation_listeners.add( l ); 1959 1960 if ( activation_listeners.size() == 1 ){ 1961 1962 download_manager.addActivationListener( this ); 1963 } 1964 }finally{ 1965 1966 peer_listeners_mon.exit(); 1967 } 1968 } 1969 1970 public void removeActivationListener( DownloadActivationListener l )1971 removeActivationListener( 1972 DownloadActivationListener l ) 1973 { 1974 try{ 1975 peer_listeners_mon.enter(); 1976 1977 activation_listeners.remove( l ); 1978 1979 if ( activation_listeners.size() == 0 ){ 1980 1981 download_manager.removeActivationListener( this ); 1982 } 1983 }finally{ 1984 1985 peer_listeners_mon.exit(); 1986 } 1987 } 1988 addCompletionListener(DownloadCompletionListener l)1989 public void addCompletionListener(DownloadCompletionListener l) { 1990 try { 1991 listeners_mon.enter(); 1992 this.completion_listeners.add(l); 1993 } 1994 finally{ 1995 listeners_mon.exit(); 1996 } 1997 } 1998 removeCompletionListener(DownloadCompletionListener l)1999 public void removeCompletionListener(DownloadCompletionListener l) { 2000 try { 2001 listeners_mon.enter(); 2002 this.completion_listeners.remove(l); 2003 } 2004 finally{ 2005 listeners_mon.exit(); 2006 } 2007 } 2008 2009 public PeerManager getPeerManager()2010 getPeerManager() 2011 { 2012 PEPeerManager pm = download_manager.getPeerManager(); 2013 2014 if ( pm == null ){ 2015 2016 return( null ); 2017 } 2018 2019 return( PeerManagerImpl.getPeerManager( pm)); 2020 } 2021 2022 public DiskManager getDiskManager()2023 getDiskManager() 2024 { 2025 PeerManager pm = getPeerManager(); 2026 2027 if ( pm != null ){ 2028 2029 return( pm.getDiskManager()); 2030 } 2031 2032 return( null ); 2033 } 2034 getDiskManagerFileCount()2035 public int getDiskManagerFileCount() { 2036 return download_manager.getNumFileInfos(); 2037 } 2038 getDiskManagerFileInfo(int index)2039 public DiskManagerFileInfo getDiskManagerFileInfo(int index) { 2040 org.gudy.azureus2.core3.disk.DiskManagerFileInfo[] info = download_manager.getDiskManagerFileInfo(); 2041 2042 if (info == null) { 2043 return null; 2044 } 2045 if (index < 0 || index >= info.length) { 2046 return null; 2047 } 2048 2049 return new DiskManagerFileInfoImpl(this, info[index]); 2050 } 2051 2052 public DiskManagerFileInfo getPrimaryFile()2053 getPrimaryFile() { 2054 org.gudy.azureus2.core3.disk.DiskManagerFileInfo primaryFile = download_manager.getDownloadState().getPrimaryFile(); 2055 2056 if (primaryFile == null) { 2057 return null; 2058 } 2059 return new DiskManagerFileInfoImpl(this, primaryFile); 2060 } 2061 2062 public DiskManagerFileInfo[] getDiskManagerFileInfo()2063 getDiskManagerFileInfo() 2064 { 2065 org.gudy.azureus2.core3.disk.DiskManagerFileInfo[] info = download_manager.getDiskManagerFileInfo(); 2066 2067 if ( info == null ){ 2068 2069 return( new DiskManagerFileInfo[0] ); 2070 } 2071 2072 DiskManagerFileInfo[] res = new DiskManagerFileInfo[info.length]; 2073 2074 for (int i=0;i<res.length;i++){ 2075 2076 res[i] = new DiskManagerFileInfoImpl( this, info[i] ); 2077 } 2078 2079 return( res ); 2080 } 2081 2082 public void setMaximumDownloadKBPerSecond( int kb )2083 setMaximumDownloadKBPerSecond( 2084 int kb ) 2085 { 2086 if(kb==-1){ 2087 Debug.out("setMaximiumDownloadKBPerSecond got value (-1) ZERO_DOWNLOAD. (-1)"+ 2088 "does not work through this method, use getDownloadRateLimitBytesPerSecond() instead."); 2089 }//if 2090 2091 download_manager.getStats().setDownloadRateLimitBytesPerSecond( kb < 0 ? 0 : kb*1024 ); 2092 } 2093 2094 public int getMaximumDownloadKBPerSecond() { 2095 int bps = download_manager.getStats().getDownloadRateLimitBytesPerSecond(); 2096 return bps <= 0 ? bps : (bps < 1024 ? 1 : bps / 1024); 2097 } 2098 2099 public int getUploadRateLimitBytesPerSecond() { 2100 return download_manager.getStats().getUploadRateLimitBytesPerSecond(); 2101 } 2102 2103 public void setUploadRateLimitBytesPerSecond( int max_rate_bps ) { 2104 download_manager.getStats().setUploadRateLimitBytesPerSecond( max_rate_bps ); 2105 } 2106 2107 public int getDownloadRateLimitBytesPerSecond() { 2108 return download_manager.getStats().getDownloadRateLimitBytesPerSecond(); 2109 } 2110 2111 public void setDownloadRateLimitBytesPerSecond( int max_rate_bps ) { 2112 download_manager.getStats().setDownloadRateLimitBytesPerSecond( max_rate_bps ); 2113 } 2114 2115 public void 2116 addRateLimiter( 2117 RateLimiter limiter, 2118 boolean is_upload ) 2119 { 2120 download_manager.addRateLimiter( UtilitiesImpl.wrapLimiter( limiter, false ), is_upload ); 2121 } 2122 2123 public void 2124 removeRateLimiter( 2125 RateLimiter limiter, 2126 boolean is_upload ) 2127 { 2128 download_manager.removeRateLimiter( UtilitiesImpl.wrapLimiter( limiter, false ), is_upload ); 2129 } 2130 2131 public int getSeedingRank() { 2132 return download_manager.getSeedingRank(); 2133 } 2134 2135 public void setSeedingRank(int rank) { 2136 download_manager.setSeedingRank(rank); 2137 } 2138 2139 public String 2140 getSavePath() 2141 { 2142 return( download_manager.getSaveLocation().toString()); 2143 } 2144 2145 public void 2146 moveDataFiles( 2147 File new_parent_dir ) 2148 2149 throws DownloadException 2150 { 2151 try{ 2152 download_manager.moveDataFiles( new_parent_dir ); 2153 2154 }catch( DownloadManagerException e ){ 2155 2156 throw( new DownloadException("move operation failed", e )); 2157 } 2158 } 2159 2160 public void moveDataFiles(File new_parent_dir, String new_name) 2161 2162 throws DownloadException 2163 { 2164 try{ 2165 download_manager.moveDataFiles( new_parent_dir, new_name ); 2166 2167 }catch( DownloadManagerException e ){ 2168 2169 throw( new DownloadException("move / rename operation failed", e )); 2170 } 2171 } 2172 2173 public void renameDownload(String new_name) throws DownloadException { 2174 try {download_manager.renameDownload(new_name);} 2175 catch (DownloadManagerException e) { 2176 throw new DownloadException("rename operation failed", e); 2177 } 2178 } 2179 2180 public void 2181 moveTorrentFile( 2182 File new_parent_dir ) 2183 2184 throws DownloadException 2185 { 2186 try{ 2187 download_manager.moveTorrentFile( new_parent_dir ); 2188 2189 }catch( DownloadManagerException e ){ 2190 2191 throw( new DownloadException("move operation failed", e )); 2192 } 2193 } 2194 2195 /** 2196 * @deprecated 2197 */ 2198 public File[] calculateDefaultPaths(boolean for_moving) { 2199 SaveLocationChange slc = this.calculateDefaultDownloadLocation(); 2200 if (slc == null) {return null;} 2201 return new File[] {slc.download_location, slc.torrent_location}; 2202 } 2203 2204 public boolean isInDefaultSaveDir() { 2205 return download_manager.isInDefaultSaveDir(); 2206 } 2207 2208 public void 2209 requestTrackerAnnounce() 2210 { 2211 download_manager.requestTrackerAnnounce( false ); 2212 } 2213 2214 public void 2215 requestTrackerAnnounce( 2216 boolean immediate ) 2217 { 2218 download_manager.requestTrackerAnnounce( immediate ); 2219 } 2220 2221 public void 2222 requestTrackerScrape( 2223 boolean immediate ) 2224 { 2225 download_manager.requestTrackerScrape( immediate ); 2226 } 2227 2228 public byte[] getDownloadPeerId() { 2229 TRTrackerAnnouncer announcer = download_manager.getTrackerClient(); 2230 if(announcer == null) return null; 2231 return announcer.getPeerId(); 2232 } 2233 2234 2235 public boolean isMessagingEnabled() { return download_manager.getExtendedMessagingMode() == BTHandshake.AZ_RESERVED_MODE; } 2236 2237 public void setMessagingEnabled( boolean enabled ) { 2238 throw new RuntimeException("setMessagingEnabled is in the process of being removed - if you are seeing this error, let the Azureus developers know that you need this method to stay!"); 2239 //download_manager.setAZMessagingEnabled( enabled ); 2240 } 2241 2242 2243 // Deprecated methods 2244 2245 public int getPriority() { 2246 return 0; 2247 } 2248 2249 public boolean isPriorityLocked() { 2250 return false; 2251 } 2252 2253 public void setPriority(int priority) { 2254 } 2255 2256 public boolean isRemoved() { 2257 return( download_manager.isDestroyed()); 2258 } 2259 // Pass LogRelation off to core objects 2260 2261 /* (non-Javadoc) 2262 * @see org.gudy.azureus2.core3.logging.LogRelation#getLogRelationText() 2263 */ 2264 public String getRelationText() { 2265 return propogatedRelationText(download_manager); 2266 } 2267 2268 /* (non-Javadoc) 2269 * @see org.gudy.azureus2.core3.logging.LogRelation#getQueryableInterfaces() 2270 */ 2271 public Object[] getQueryableInterfaces() { 2272 return new Object[] { download_manager }; 2273 } 2274 2275 private CopyOnWriteMap getAttributeMapForType(int event_type) { 2276 return event_type == DownloadPropertyEvent.PT_TORRENT_ATTRIBUTE_WILL_BE_READ ? read_attribute_listeners_map_cow : write_attribute_listeners_map_cow; 2277 } 2278 2279 public boolean canMoveDataFiles() { 2280 return download_manager.canMoveDataFiles(); 2281 } 2282 2283 public void attributeEventOccurred(DownloadManager download, String attribute, int event_type) { 2284 CopyOnWriteMap attr_listener_map = getAttributeMapForType(event_type); 2285 2286 TorrentAttribute attr = convertAttribute(attribute); 2287 if (attr == null) {return;} 2288 2289 List listeners = null; 2290 listeners = ((CopyOnWriteList)attr_listener_map.get(attribute)).getList(); 2291 2292 if (listeners == null) {return;} 2293 2294 for (int i=0; i<listeners.size(); i++) { 2295 DownloadAttributeListener dal = (DownloadAttributeListener)listeners.get(i); 2296 try {dal.attributeEventOccurred(this, attr, event_type);} 2297 catch (Throwable t) {Debug.printStackTrace(t);} 2298 } 2299 } 2300 2301 public SaveLocationChange calculateDefaultDownloadLocation() { 2302 return DownloadManagerMoveHandler.recalculatePath(this.download_manager); 2303 } 2304 2305 public Object getUserData( Object key ){ 2306 return( download_manager.getUserData(key)); 2307 } 2308 2309 public void setUserData( Object key, Object data ){ 2310 download_manager.setUserData(key, data); 2311 } 2312 2313 public void startDownload(boolean force) { 2314 if (force) { 2315 this.setForceStart(true); 2316 return; 2317 } 2318 this.setForceStart(false); 2319 2320 int state = this.getState(); 2321 if (state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_QUEUED) { 2322 download_manager.setStateWaiting(); 2323 } 2324 2325 } 2326 2327 public void stopDownload() { 2328 if (download_manager.getState() == DownloadManager.STATE_STOPPED) {return;} 2329 download_manager.stopIt(DownloadManager.STATE_STOPPED, false, false); 2330 } 2331 2332 // stub stuff 2333 2334 public boolean 2335 isStub() 2336 { 2337 return( false ); 2338 } 2339 2340 public boolean 2341 canStubbify() 2342 { 2343 return( manager.canStubbify( this )); 2344 } 2345 2346 public DownloadStub 2347 stubbify() 2348 2349 throws DownloadException, DownloadRemovalVetoException 2350 { 2351 return( manager.stubbify( this )); 2352 } 2353 2354 public Download 2355 destubbify() 2356 2357 throws DownloadException 2358 { 2359 return( this ); 2360 } 2361 2362 public List<DistributedDatabase> 2363 getDistributedDatabases() 2364 { 2365 return( DDBaseImpl.getDDBs( this )); 2366 } 2367 2368 public byte[] 2369 getTorrentHash() 2370 { 2371 Torrent t = getTorrent(); 2372 2373 if ( t == null ){ 2374 2375 return( null ); 2376 } 2377 2378 return( t.getHash()); 2379 } 2380 2381 2382 public long 2383 getTorrentSize() 2384 { 2385 Torrent t = getTorrent(); 2386 2387 if ( t == null ){ 2388 2389 return( 0 ); 2390 } 2391 2392 return( t.getSize()); 2393 } 2394 2395 public DownloadStubFile[] 2396 getStubFiles() 2397 { 2398 DiskManagerFileInfo[] dm_files = getDiskManagerFileInfo(); 2399 2400 DownloadStubFile[] files = new DownloadStubFile[dm_files.length]; 2401 2402 for ( int i=0;i<files.length;i++){ 2403 2404 final DiskManagerFileInfo dm_file = dm_files[i]; 2405 2406 files[i] = 2407 new DownloadStubFile() 2408 { 2409 public File 2410 getFile() 2411 { 2412 return( dm_file.getFile( true )); 2413 } 2414 2415 public long 2416 getLength() 2417 { 2418 if ( dm_file.getDownloaded() == dm_file.getLength() && !dm_file.isSkipped()){ 2419 2420 return( dm_file.getLength()); 2421 2422 }else{ 2423 2424 return( -dm_file.getLength()); 2425 } 2426 } 2427 }; 2428 } 2429 2430 return( files ); 2431 } 2432 2433 2434 public void changeLocation(SaveLocationChange slc) throws DownloadException { 2435 2436 // No change in the file. 2437 boolean has_change = slc.hasDownloadChange() || slc.hasTorrentChange(); 2438 if (!has_change) {return;} 2439 2440 // Test that one of the locations is actually different. 2441 has_change = slc.isDifferentDownloadLocation(new File(this.getSavePath())); 2442 if (!has_change) { 2443 has_change = slc.isDifferentTorrentLocation(new File(this.getTorrentFileName())); 2444 } 2445 2446 if (!has_change) {return;} 2447 2448 boolean try_to_resume = !this.isPaused(); 2449 try { 2450 try { 2451 if (slc.hasDownloadChange()) {download_manager.moveDataFiles(slc.download_location, slc.download_name);} 2452 if (slc.hasTorrentChange()) {download_manager.moveTorrentFile(slc.torrent_location, slc.torrent_name);} 2453 } 2454 catch (DownloadManagerException e) { 2455 throw new DownloadException(e.getMessage(), e); 2456 } 2457 } 2458 finally { 2459 if (try_to_resume) {this.resume();} 2460 } 2461 2462 } 2463 2464 private static class PropertyListenerBridge implements DownloadAttributeListener { 2465 private DownloadPropertyListener l; 2466 public PropertyListenerBridge(DownloadPropertyListener l) {this.l = l;} 2467 public void attributeEventOccurred(Download d, final TorrentAttribute attr, final int event_type) { 2468 l.propertyChanged(d, new DownloadPropertyEvent() { 2469 public int getType() {return event_type;} 2470 public Object getData() {return attr;} 2471 }); 2472 } 2473 } 2474 2475 private static class 2476 AggregateScrapeResult 2477 implements DownloadScrapeResult 2478 { 2479 private Download dl; 2480 2481 private TRTrackerScraperResponse response; 2482 2483 private int seeds; 2484 private int leechers; 2485 2486 private int time_secs; 2487 2488 private 2489 AggregateScrapeResult( 2490 Download _dl ) 2491 { 2492 dl = _dl; 2493 } 2494 2495 private void 2496 update( 2497 TRTrackerScraperResponse _response, 2498 int _seeds, 2499 int _peers, 2500 int _time_secs ) 2501 { 2502 response = _response; 2503 seeds = _seeds; 2504 leechers = _peers; 2505 time_secs = _time_secs; 2506 } 2507 2508 public Download 2509 getDownload() 2510 { 2511 return( dl ); 2512 } 2513 2514 public int 2515 getResponseType() 2516 { 2517 return( RT_SUCCESS ); 2518 } 2519 2520 public int 2521 getSeedCount() 2522 { 2523 return( seeds ); 2524 } 2525 2526 public int 2527 getNonSeedCount() 2528 { 2529 return( leechers ); 2530 } 2531 2532 public long 2533 getScrapeStartTime() 2534 { 2535 TRTrackerScraperResponse r = response; 2536 2537 if ( r != null ){ 2538 2539 return( r.getScrapeStartTime()); 2540 } 2541 2542 if ( time_secs <= 0 ){ 2543 2544 return( -1 ); 2545 2546 }else{ 2547 2548 return( time_secs * 1000L ); 2549 } 2550 } 2551 2552 public void 2553 setNextScrapeStartTime( 2554 long nextScrapeStartTime) 2555 { 2556 Debug.out( "Not Supported" ); 2557 } 2558 2559 public long 2560 getNextScrapeStartTime() 2561 { 2562 TRTrackerScraperResponse r = response; 2563 2564 return( r == null?-1:r.getScrapeStartTime()); 2565 } 2566 2567 public String 2568 getStatus() 2569 { 2570 return( "Aggregate Scrape" ); 2571 } 2572 2573 public URL 2574 getURL() 2575 { 2576 TRTrackerScraperResponse r = response; 2577 2578 return( r == null?null:r.getURL()); 2579 } 2580 } 2581 }