/* * TorrentDownloaderFactory.java * * Created on 2. November 2003, 03:52 * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved. * * 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, or (at your option) any later version. * 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. * 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. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package org.gudy.azureus2.core3.torrentdownloader; import java.io.File; import java.net.URL; import java.util.HashMap; import java.util.Map; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.torrentdownloader.impl.TorrentDownloaderImpl; import org.gudy.azureus2.core3.torrentdownloader.impl.TorrentDownloaderManager; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.UrlUtils; import com.aelitis.azureus.core.proxy.AEProxyFactory; import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy; /** * * @author Tobias Minich */ public class TorrentDownloaderFactory { private static TorrentDownloaderImpl getClass(boolean logged) { try { return (TorrentDownloaderImpl) Class.forName("org.gudy.azureus2.core3.torrentdownloader.impl.TorrentDownloader"+(logged?"Logged":"")+"Impl").newInstance(); } catch (Exception e) { Debug.printStackTrace( e ); return null; } } /** * creates and initializes a TorrentDownloader object with the specified parameters. * NOTE: this does not actually start the TorrentDownloader object * @param callback object to notify about torrent download status * @param url url of torrent file to download * @param referrer url of referrer to set as HTTP_REFERER header when requesting torrent * @param fileordir path to a file or directory that the actual * torrent file should be saved to. if a default save directory is not specified, this will be used instead. * even if a default save directory is specified, if this parameter path refers to a file, the filename will * be used when saving the torrent * @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 * @return */ public static TorrentDownloader create( TorrentDownloaderCallBackInterface callback, String url, String referrer, String fileordir, boolean logged ) { return( create( callback, url, referrer, null, fileordir, logged )); } public static TorrentDownloader create( TorrentDownloaderCallBackInterface callback, String url, String referrer, String fileordir ) { return create(callback, url, referrer, fileordir, false ); } public static TorrentDownloader create( TorrentDownloaderCallBackInterface callback, String url, String referrer, Map request_properties, String fileordir) { return( create( callback, url, referrer, request_properties, fileordir, false )); } private static TorrentDownloader create( TorrentDownloaderCallBackInterface callback, String url, String referrer, Map request_properties, String fileordir, boolean logged ) { return( new TorrentDownloadRetrier( callback, url, referrer, request_properties, fileordir, logged )); } public static TorrentDownloader create(TorrentDownloaderCallBackInterface callback, String url, boolean logged) { return create(callback, url, null, null, logged); } public static TorrentDownloader create(TorrentDownloaderCallBackInterface callback, String url) { return create(callback, url, null, null, false); } public static TorrentDownloader create(String url, String fileordir, boolean logged) { return create(null, url, null, fileordir, logged); } public static TorrentDownloader create(String url, String fileordir) { return create(null, url, null, fileordir, false); } public static TorrentDownloader create(String url, boolean logged) { return create(null, url, null, null, logged); } public static TorrentDownloader create(String url) { return create(null, url, null, null, false); } public static void initManager(GlobalManager gm, boolean logged, boolean autostart, String downloaddir) { TorrentDownloaderManager.getInstance().init(gm, logged, autostart, downloaddir); } public static TorrentDownloader downloadManaged(String url, String fileordir, boolean logged) { return TorrentDownloaderManager.getInstance().download(url, fileordir, logged); } public static TorrentDownloader downloadManaged(String url, String fileordir) { return TorrentDownloaderManager.getInstance().download(url, fileordir); } public static TorrentDownloader downloadManaged(String url, boolean logged) { return TorrentDownloaderManager.getInstance().download(url, logged); } public static TorrentDownloader downloadManaged(String url) { return TorrentDownloaderManager.getInstance().download(url); } private static class TorrentDownloadRetrier implements TorrentDownloader { final private String url; final private String referrer; final private Map request_properties; final private String fileordir; final private boolean logged; private volatile TorrentDownloaderImpl delegate; private volatile boolean cancelled; private volatile boolean sdp_set; private volatile String sdp_path; private volatile String sdp_file; private volatile boolean dfoc_set; private volatile boolean dfoc; private volatile boolean irc_set; private volatile boolean irc; private volatile String original_error; private TorrentDownloadRetrier( final TorrentDownloaderCallBackInterface _callback, String _url, String _referrer, Map _request_properties, String _fileordir, boolean _logged ) { url = _url; referrer = _referrer; request_properties = _request_properties; fileordir = _fileordir; logged = _logged; TorrentDownloaderCallBackInterface callback = new TorrentDownloaderCallBackInterface() { private TorrentDownloaderCallBackInterface original_callback = _callback; private boolean no_retry = original_callback == null; private boolean init_reported = false; private boolean start_reported = false; private boolean finish_reported = false; private boolean proxy_tried = false; private PluginProxy plugin_proxy; public void TorrentDownloaderEvent( int state, TorrentDownloader _delegate ) { if ( _delegate != delegate ){ return; } if ( state == STATE_ERROR ){ if ( original_error == null ){ original_error = delegate.getError(); } } if ( plugin_proxy != null && ( state == STATE_FINISHED || state == STATE_DUPLICATE || state == STATE_CANCELLED || state == STATE_ERROR )){ plugin_proxy.setOK( state != STATE_ERROR ); plugin_proxy = null; } synchronized( this ){ if ( state == STATE_INIT ){ if ( init_reported ){ return; } init_reported = true; } if ( state == STATE_START ){ if ( start_reported ){ return; } start_reported = true; } if ( state == STATE_FINISHED ){ if ( finish_reported ){ return; } finish_reported = true; } } if ( cancelled ){ no_retry = true; } if ( no_retry ){ if ( original_callback != null ){ original_callback.TorrentDownloaderEvent( state, TorrentDownloadRetrier.this ); } return; } if ( state == STATE_FINISHED || state == STATE_DUPLICATE || state == STATE_CANCELLED ){ if ( original_callback != null ){ original_callback.TorrentDownloaderEvent( state, TorrentDownloadRetrier.this ); } no_retry = true; return; } if ( state == STATE_ERROR ){ String lc_url = url.toLowerCase().trim(); if ( !proxy_tried ){ proxy_tried = true; if ( lc_url.startsWith( "http" )){ try{ URL original_url = new URL( url ); plugin_proxy = AEProxyFactory.getPluginProxy( "loading plugin details", original_url ); if ( plugin_proxy != null ){ delegate = TorrentDownloaderFactory.getClass( logged ); if ( sdp_set ){ delegate.setDownloadPath( sdp_path, sdp_file ); } if ( dfoc_set ){ delegate.setDeleteFileOnCancel( dfoc ); } if ( irc_set ){ delegate.setIgnoreReponseCode( irc ); } Map props = new HashMap(); if ( request_properties != null ){ props.putAll( request_properties ); } props.put( "HOST", plugin_proxy.getURLHostRewrite() + (original_url.getPort()==-1?"":(":"+original_url.getPort()))); delegate.init( this, plugin_proxy.getURL().toExternalForm(), plugin_proxy.getProxy(), referrer, props, fileordir ); delegate.start(); return; } }catch( Throwable e ){ } } } String retry_url = null; if ( lc_url.startsWith( "http" )){ retry_url = UrlUtils.parseTextForURL( url.substring( 5 ), true ); } if ( retry_url != null ){ delegate = TorrentDownloaderFactory.getClass( logged ); if ( sdp_set ){ delegate.setDownloadPath( sdp_path, sdp_file ); } if ( dfoc_set ){ delegate.setDeleteFileOnCancel( dfoc ); } if ( irc_set ){ delegate.setIgnoreReponseCode( irc ); } delegate.init( this, retry_url, null, referrer, request_properties, fileordir ); no_retry = true; delegate.start(); return; }else{ no_retry = true; } } if ( original_callback != null ){ original_callback.TorrentDownloaderEvent( state, TorrentDownloadRetrier.this ); } } }; delegate = TorrentDownloaderFactory.getClass( logged ); delegate.init( callback, url, null, referrer, request_properties, fileordir ); } public void start() { delegate.start(); } public void cancel() { cancelled = true; delegate.cancel(); } public void setDownloadPath( String path, String file) { sdp_set = true; sdp_path = path; sdp_file = file; delegate.setDownloadPath(path, file); } public int getDownloadState() { return( delegate.getDownloadState()); } public File getFile() { return( delegate.getFile()); } public int getPercentDone() { return( delegate.getPercentDone()); } public int getTotalRead() { return( delegate.getTotalRead()); } public String getError() { if ( original_error != null ){ return( original_error ); } return( delegate.getError()); } public String getStatus() { return( delegate.getStatus()); } public String getURL() { return( delegate.getURL()); } public int getLastReadCount() { return( delegate.getLastReadCount()); } public byte[] getLastReadBytes() { return( delegate.getLastReadBytes()); } public boolean getDeleteFileOnCancel() { return( delegate.getDeleteFileOnCancel()); } public void setDeleteFileOnCancel( boolean deleteFileOnCancel ) { dfoc_set = true; dfoc = deleteFileOnCancel; delegate.setDeleteFileOnCancel( deleteFileOnCancel ); } public boolean isIgnoreReponseCode() { return( delegate.isIgnoreReponseCode()); } public void setIgnoreReponseCode( boolean ignoreReponseCode) { irc_set = true; irc = ignoreReponseCode; delegate.setIgnoreReponseCode( ignoreReponseCode ); } } }