1 /* 2 * TorrentDownloaderFactory.java 3 * 4 * Created on 2. November 2003, 03:52 5 * Copyright (C) Azureus Software, Inc, All Rights Reserved. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 */ 19 20 package org.gudy.azureus2.core3.torrentdownloader; 21 22 import java.io.File; 23 import java.net.URL; 24 import java.util.HashMap; 25 import java.util.Map; 26 27 import org.gudy.azureus2.core3.global.GlobalManager; 28 import org.gudy.azureus2.core3.torrentdownloader.impl.TorrentDownloaderImpl; 29 import org.gudy.azureus2.core3.torrentdownloader.impl.TorrentDownloaderManager; 30 import org.gudy.azureus2.core3.util.AENetworkClassifier; 31 import org.gudy.azureus2.core3.util.Debug; 32 import org.gudy.azureus2.core3.util.TorrentUtils; 33 import org.gudy.azureus2.core3.util.UrlUtils; 34 35 import com.aelitis.azureus.core.proxy.AEProxyFactory; 36 import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy; 37 38 /** 39 * 40 * @author Tobias Minich 41 */ 42 public class TorrentDownloaderFactory { 43 getClass(boolean logged)44 private static TorrentDownloaderImpl getClass(boolean logged) { 45 try { 46 return (TorrentDownloaderImpl) Class.forName("org.gudy.azureus2.core3.torrentdownloader.impl.TorrentDownloader"+(logged?"Logged":"")+"Impl").newInstance(); 47 } catch (Exception e) { 48 Debug.printStackTrace( e ); 49 return null; 50 } 51 } 52 53 /** 54 * creates and initializes a TorrentDownloader object with the specified parameters. 55 * NOTE: this does not actually start the TorrentDownloader object 56 * @param callback object to notify about torrent download status 57 * @param url url of torrent file to download 58 * @param referrer url of referrer to set as HTTP_REFERER header when requesting torrent 59 * @param fileordir path to a file or directory that the actual 60 * torrent file should be saved to. if a default save directory is not specified, this will be used instead. 61 * even if a default save directory is specified, if this parameter path refers to a file, the filename will 62 * be used when saving the torrent 63 * @param whether or not logging is enabled for the torrent download. this is performed through the TorrentDownloaderLoggedImpl class which is only available in the uis project 64 * @return 65 */ 66 public static TorrentDownloader create( TorrentDownloaderCallBackInterface callback, String url, String referrer, String fileordir, boolean logged )67 create( 68 TorrentDownloaderCallBackInterface callback, 69 String url, 70 String referrer, 71 String fileordir, 72 boolean logged ) 73 { 74 return( create( callback, url, referrer, null, fileordir, logged )); 75 } 76 77 public static TorrentDownloader create( TorrentDownloaderCallBackInterface callback, String url, String referrer, String fileordir )78 create( 79 TorrentDownloaderCallBackInterface callback, 80 String url, 81 String referrer, 82 String fileordir ) 83 { 84 return create(callback, url, referrer, fileordir, false ); 85 } 86 87 public static TorrentDownloader create( TorrentDownloaderCallBackInterface callback, String url, String referrer, Map request_properties, String fileordir)88 create( 89 TorrentDownloaderCallBackInterface callback, 90 String url, 91 String referrer, 92 Map request_properties, 93 String fileordir) 94 { 95 return( create( callback, url, referrer, request_properties, fileordir, false )); 96 } 97 98 private static TorrentDownloader create( TorrentDownloaderCallBackInterface callback, String url, String referrer, Map request_properties, String fileordir, boolean logged )99 create( 100 TorrentDownloaderCallBackInterface callback, 101 String url, 102 String referrer, 103 Map request_properties, 104 String fileordir, 105 boolean logged ) 106 { 107 return( new TorrentDownloadRetrier( callback, url, referrer, request_properties, fileordir, logged )); 108 } 109 create(TorrentDownloaderCallBackInterface callback, String url, boolean logged)110 public static TorrentDownloader create(TorrentDownloaderCallBackInterface callback, String url, boolean logged) { 111 return create(callback, url, null, null, logged); 112 } 113 create(TorrentDownloaderCallBackInterface callback, String url)114 public static TorrentDownloader create(TorrentDownloaderCallBackInterface callback, String url) { 115 return create(callback, url, null, null, false); 116 } 117 create(String url, String fileordir, boolean logged)118 public static TorrentDownloader create(String url, String fileordir, boolean logged) { 119 return create(null, url, null, fileordir, logged); 120 } 121 create(String url, String fileordir)122 public static TorrentDownloader create(String url, String fileordir) { 123 return create(null, url, null, fileordir, false); 124 } 125 create(String url, boolean logged)126 public static TorrentDownloader create(String url, boolean logged) { 127 return create(null, url, null, null, logged); 128 } 129 create(String url)130 public static TorrentDownloader create(String url) { 131 return create(null, url, null, null, false); 132 } 133 initManager(GlobalManager gm, boolean logged, boolean autostart, String downloaddir)134 public static void initManager(GlobalManager gm, boolean logged, boolean autostart, String downloaddir) { 135 TorrentDownloaderManager.getInstance().init(gm, logged, autostart, downloaddir); 136 } 137 downloadManaged(String url, String fileordir, boolean logged)138 public static TorrentDownloader downloadManaged(String url, String fileordir, boolean logged) { 139 return TorrentDownloaderManager.getInstance().download(url, fileordir, logged); 140 } 141 downloadManaged(String url, String fileordir)142 public static TorrentDownloader downloadManaged(String url, String fileordir) { 143 return TorrentDownloaderManager.getInstance().download(url, fileordir); 144 } 145 downloadManaged(String url, boolean logged)146 public static TorrentDownloader downloadManaged(String url, boolean logged) { 147 return TorrentDownloaderManager.getInstance().download(url, logged); 148 } 149 downloadManaged(String url)150 public static TorrentDownloader downloadManaged(String url) { 151 return TorrentDownloaderManager.getInstance().download(url); 152 } 153 154 private static class 155 TorrentDownloadRetrier 156 implements TorrentDownloader 157 { 158 final private String url; 159 final private String referrer; 160 final private Map request_properties; 161 final private String fileordir; 162 final private boolean logged; 163 164 private volatile TorrentDownloaderImpl delegate; 165 166 private volatile boolean cancelled; 167 168 private volatile boolean sdp_set; 169 private volatile String sdp_path; 170 private volatile String sdp_file; 171 172 private volatile boolean dfoc_set; 173 private volatile boolean dfoc; 174 private volatile boolean irc_set; 175 private volatile boolean irc; 176 177 private volatile String original_error; 178 179 private TorrentDownloadRetrier( final TorrentDownloaderCallBackInterface _callback, String _url, String _referrer, Map _request_properties, String _fileordir, boolean _logged )180 TorrentDownloadRetrier( 181 final TorrentDownloaderCallBackInterface _callback, 182 String _url, 183 String _referrer, 184 Map _request_properties, 185 String _fileordir, 186 boolean _logged ) 187 { 188 url = _url; 189 referrer = _referrer; 190 request_properties = _request_properties; 191 fileordir = _fileordir; 192 logged = _logged; 193 194 TorrentDownloaderCallBackInterface callback = 195 new TorrentDownloaderCallBackInterface() 196 { 197 private TorrentDownloaderCallBackInterface original_callback = _callback; 198 199 private boolean no_retry = original_callback == null; 200 201 private boolean init_reported = false; 202 private boolean start_reported = false; 203 private boolean finish_reported = false; 204 205 private boolean proxy_tried = false; 206 private PluginProxy plugin_proxy; 207 208 public void 209 TorrentDownloaderEvent( 210 int state, 211 TorrentDownloader _delegate ) 212 { 213 if ( _delegate != delegate ){ 214 215 return; 216 } 217 218 if ( state == STATE_ERROR ){ 219 220 if ( original_error == null ){ 221 222 original_error = delegate.getError(); 223 } 224 } 225 226 if ( plugin_proxy != null && 227 ( state == STATE_FINISHED || 228 state == STATE_DUPLICATE || 229 state == STATE_CANCELLED || 230 state == STATE_ERROR )){ 231 232 plugin_proxy.setOK( state != STATE_ERROR ); 233 234 plugin_proxy = null; 235 } 236 237 238 synchronized( this ){ 239 240 if ( state == STATE_INIT ){ 241 242 if ( init_reported ){ 243 244 return; 245 } 246 247 init_reported = true; 248 } 249 250 if ( state == STATE_START ){ 251 252 if ( start_reported ){ 253 254 return; 255 } 256 257 start_reported = true; 258 } 259 260 if ( state == STATE_FINISHED ){ 261 262 if ( finish_reported ){ 263 264 return; 265 } 266 267 finish_reported = true; 268 } 269 } 270 271 if ( cancelled ){ 272 273 no_retry = true; 274 } 275 276 if ( no_retry ){ 277 278 if ( original_callback != null ){ 279 280 original_callback.TorrentDownloaderEvent( state, TorrentDownloadRetrier.this ); 281 } 282 283 return; 284 } 285 286 if ( state == STATE_FINISHED || 287 state == STATE_DUPLICATE || 288 state == STATE_CANCELLED ){ 289 290 if ( state == STATE_FINISHED && proxy_tried ){ 291 292 TorrentUtils.setObtainedFrom( delegate.getFile(), url ); 293 } 294 295 if ( original_callback != null ){ 296 297 original_callback.TorrentDownloaderEvent( state, TorrentDownloadRetrier.this ); 298 } 299 300 no_retry = true; 301 302 return; 303 } 304 305 if ( state == STATE_ERROR ){ 306 307 String lc_url = url.toLowerCase().trim(); 308 309 if ( !proxy_tried ){ 310 311 proxy_tried = true; 312 313 boolean tor_hack = lc_url.startsWith( "tor:" ); 314 315 if ( lc_url.startsWith( "http" ) || tor_hack ){ 316 317 try{ 318 URL original_url; 319 320 if ( tor_hack ){ 321 322 original_url = new URL( url.substring( 4 )); 323 324 Map<String,Object> options = new HashMap<String,Object>(); 325 326 options.put( AEProxyFactory.PO_PEER_NETWORKS, new String[]{ AENetworkClassifier.AT_TOR }); 327 328 plugin_proxy = 329 AEProxyFactory.getPluginProxy( 330 "torrent download", 331 original_url, 332 options, 333 true ); 334 }else{ 335 336 original_url = new URL( url ); 337 } 338 339 plugin_proxy = AEProxyFactory.getPluginProxy( "torrent download", original_url ); 340 341 if ( plugin_proxy != null ){ 342 343 delegate = TorrentDownloaderFactory.getClass( logged ); 344 345 if ( sdp_set ){ 346 347 delegate.setDownloadPath( sdp_path, sdp_file ); 348 } 349 350 if ( dfoc_set ){ 351 352 delegate.setDeleteFileOnCancel( dfoc ); 353 } 354 355 if ( irc_set ){ 356 357 delegate.setIgnoreReponseCode( irc ); 358 } 359 360 Map props = new HashMap(); 361 362 if ( request_properties != null ){ 363 364 props.putAll( request_properties ); 365 } 366 367 props.put( "HOST", plugin_proxy.getURLHostRewrite() + (original_url.getPort()==-1?"":(":"+original_url.getPort()))); 368 369 delegate.init( this, plugin_proxy.getURL().toExternalForm(), plugin_proxy.getProxy(), referrer, props, fileordir ); 370 371 delegate.start(); 372 373 return; 374 } 375 }catch( Throwable e ){ 376 377 } 378 } 379 } 380 381 String retry_url = null; 382 383 if ( lc_url.startsWith( "http" )){ 384 385 retry_url = UrlUtils.parseTextForURL( url.substring( 5 ), true ); 386 } 387 388 if ( retry_url != null ){ 389 390 delegate = TorrentDownloaderFactory.getClass( logged ); 391 392 if ( sdp_set ){ 393 394 delegate.setDownloadPath( sdp_path, sdp_file ); 395 } 396 397 if ( dfoc_set ){ 398 399 delegate.setDeleteFileOnCancel( dfoc ); 400 } 401 402 if ( irc_set ){ 403 404 delegate.setIgnoreReponseCode( irc ); 405 } 406 407 delegate.init( this, retry_url, null, referrer, request_properties, fileordir ); 408 409 no_retry = true; 410 411 delegate.start(); 412 413 return; 414 415 }else{ 416 417 no_retry = true; 418 } 419 } 420 421 if ( original_callback != null ){ 422 423 original_callback.TorrentDownloaderEvent( state, TorrentDownloadRetrier.this ); 424 } 425 } 426 427 }; 428 429 delegate = TorrentDownloaderFactory.getClass( logged ); 430 431 delegate.init( callback, url, null, referrer, request_properties, fileordir ); 432 } 433 434 public void start()435 start() 436 { 437 delegate.start(); 438 } 439 440 public void cancel()441 cancel() 442 { 443 cancelled = true; 444 445 delegate.cancel(); 446 } 447 448 public void setDownloadPath( String path, String file)449 setDownloadPath( 450 String path, 451 String file) 452 { 453 sdp_set = true; 454 sdp_path = path; 455 sdp_file = file; 456 457 delegate.setDownloadPath(path, file); 458 } 459 460 public int getDownloadState()461 getDownloadState() 462 { 463 return( delegate.getDownloadState()); 464 } 465 466 public File getFile()467 getFile() 468 { 469 return( delegate.getFile()); 470 } 471 472 public int getPercentDone()473 getPercentDone() 474 { 475 return( delegate.getPercentDone()); 476 } 477 478 public int getTotalRead()479 getTotalRead() 480 { 481 return( delegate.getTotalRead()); 482 } 483 484 public String getError()485 getError() 486 { 487 if ( original_error != null ){ 488 489 return( original_error ); 490 } 491 492 return( delegate.getError()); 493 } 494 495 public String getStatus()496 getStatus() 497 { 498 return( delegate.getStatus()); 499 } 500 501 public String getURL()502 getURL() 503 { 504 return( delegate.getURL()); 505 } 506 507 public int getLastReadCount()508 getLastReadCount() 509 { 510 return( delegate.getLastReadCount()); 511 } 512 513 public byte[] getLastReadBytes()514 getLastReadBytes() 515 { 516 return( delegate.getLastReadBytes()); 517 } 518 519 public boolean getDeleteFileOnCancel()520 getDeleteFileOnCancel() 521 { 522 return( delegate.getDeleteFileOnCancel()); 523 } 524 525 public void setDeleteFileOnCancel( boolean deleteFileOnCancel )526 setDeleteFileOnCancel( 527 boolean deleteFileOnCancel ) 528 { 529 dfoc_set = true; 530 dfoc = deleteFileOnCancel; 531 532 delegate.setDeleteFileOnCancel( deleteFileOnCancel ); 533 } 534 535 public boolean isIgnoreReponseCode()536 isIgnoreReponseCode() 537 { 538 return( delegate.isIgnoreReponseCode()); 539 } 540 541 public void setIgnoreReponseCode( boolean ignoreReponseCode)542 setIgnoreReponseCode( 543 boolean ignoreReponseCode) 544 { 545 irc_set = true; 546 irc = ignoreReponseCode; 547 548 delegate.setIgnoreReponseCode( ignoreReponseCode ); 549 } 550 } 551 } 552