/*
* File : ProgressPanel.java
* Created : 7 oct. 2003 13:01:42
* By : Olivier
*
* 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.ui.swt.maketorrent;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.download.DownloadManagerInitialisationAdapter;
import org.gudy.azureus2.core3.internat.LocaleTorrentUtil;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.logging.LogAlert;
import org.gudy.azureus2.core3.logging.Logger;
import org.gudy.azureus2.core3.peer.PEPeerManager;
import org.gudy.azureus2.core3.torrent.*;
import org.gudy.azureus2.core3.tracker.host.TRHostException;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT.TriggerInThread;
import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel;
import org.gudy.azureus2.ui.swt.wizard.IWizardPanel;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.tag.Tag;
import com.aelitis.azureus.core.tag.TagManager;
import com.aelitis.azureus.core.tag.TagManagerFactory;
import com.aelitis.azureus.core.tag.TagType;
/**
* @author Olivier
*
*/
public class ProgressPanel extends AbstractWizardPanel<NewTorrentWizard> implements TOTorrentProgressListener {
Text tasks;
ProgressBar progress;
Display display;
Button show_torrent_file;
public ProgressPanel(NewTorrentWizard wizard, IWizardPanel<NewTorrentWizard> _previousPanel) {
super(wizard, _previousPanel);
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#show()
*/
public void show() {
display = wizard.getDisplay();
wizard.setTitle(MessageText.getString("wizard.progresstitle"));
wizard.setCurrentInfo("");
wizard.setPreviousEnabled(false);
Composite rootPanel = wizard.getPanel();
GridLayout layout = new GridLayout();
layout.numColumns = 1;
rootPanel.setLayout(layout);
Composite panel = new Composite(rootPanel, SWT.NULL);
GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL);
panel.setLayoutData(gridData);
layout = new GridLayout();
layout.numColumns = 2;
panel.setLayout(layout);
tasks = new Text(panel, SWT.BORDER | SWT.MULTI | SWT.READ_ONLY);
tasks.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
gridData = new GridData(GridData.FILL_BOTH);
gridData.heightHint = 120;
gridData.horizontalSpan = 2;
tasks.setLayoutData(gridData);
progress = new ProgressBar(panel, SWT.NULL);
progress.setMinimum(0);
progress.setMaximum(0);
gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.horizontalSpan = 2;
progress.setLayoutData(gridData);
Label label = new Label( panel, SWT.NULL);
gridData = new GridData(GridData.FILL_HORIZONTAL);
label.setLayoutData(gridData);
Composite Browsepanel = new Composite(panel, SWT.NULL);
layout = new GridLayout();
layout.numColumns = 2;
Browsepanel.setLayout(layout);
label = new Label(Browsepanel, SWT.NULL);
Messages.setLanguageText(label, "wizard.newtorrent.showtorrent" );
show_torrent_file = new Button( Browsepanel, SWT.PUSH );
Messages.setLanguageText( show_torrent_file, "MyTorrentsView.menu.explore");
show_torrent_file.addSelectionListener(
new SelectionAdapter()
{
public void
widgetSelected(
SelectionEvent e )
{
ManagerUtils.open( new File( wizard.savePath));
}
});
show_torrent_file.setEnabled( false );
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.maketorrent.IWizardPanel#finish()
*/
public void finish() {
Thread t = new AEThread("Torrent Maker") {
public void runSupport() {
makeTorrent();
}
};
t.setPriority(Thread.MIN_PRIORITY);
t.setDaemon(true);
t.start();
}
public void makeTorrent() {
int tracker_type = wizard.getTrackerType();
if( tracker_type == NewTorrentWizard.TT_EXTERNAL ){
TrackersUtil.getInstance().addTracker(wizard.trackerURL);
}
File f;
if ( wizard.create_mode == NewTorrentWizard.MODE_DIRECTORY ){
f = new File(wizard.directoryPath);
}else if ( wizard.create_mode == NewTorrentWizard.MODE_SINGLE_FILE ){
f = new File(wizard.singlePath);
}else{
f = wizard.byo_desc_file;
}
try {
URL url = new URL(wizard.trackerURL);
final TOTorrent torrent;
if ( wizard.getPieceSizeComputed()){
wizard.creator =
TOTorrentFactory.createFromFileOrDirWithComputedPieceLength(
f, url, wizard.getAddOtherHashes());
wizard.creator.addListener( this );
wizard.creator.setFileIsLayoutDescriptor( wizard.create_mode == NewTorrentWizard.MODE_BYO );
torrent = wizard.creator.create();
}else{
wizard.creator =
TOTorrentFactory.createFromFileOrDirWithFixedPieceLength(
f, url, wizard.getAddOtherHashes(), wizard.getPieceSizeManual());
wizard.creator.addListener( this );
wizard.creator.setFileIsLayoutDescriptor( wizard.create_mode == NewTorrentWizard.MODE_BYO );
torrent = wizard.creator.create();
}
if ( tracker_type == NewTorrentWizard.TT_DECENTRAL ){
TorrentUtils.setDecentralised( torrent );
}
torrent.setComment(wizard.getComment());
TorrentUtils.setDHTBackupEnabled( torrent, wizard.permitDHT );
TorrentUtils.setPrivate( torrent, wizard.privateTorrent );
LocaleTorrentUtil.setDefaultTorrentEncoding( torrent );
// mark this newly created torrent as complete to avoid rechecking on open
final File save_dir;
if ( wizard.create_mode == NewTorrentWizard.MODE_DIRECTORY ){
save_dir = f;
}else if ( wizard.create_mode == NewTorrentWizard.MODE_SINGLE_FILE ){
save_dir = f.getParentFile();
}else{
String save_path = COConfigurationManager.getStringParameter( "Default save path" );
File f_save_path = new File( save_path );
if ( !f_save_path.canWrite()){
throw( new Exception( "Default save path is not configured: See Tools->Options->File" ));
}
save_dir = f_save_path;
}
if( wizard.useMultiTracker ){
this.reportCurrentTask(MessageText.getString("wizard.addingmt"));
TorrentUtils.listToAnnounceGroups(wizard.trackers, torrent);
}
if (wizard.useWebSeed && wizard.webseeds.size() > 0 ){
this.reportCurrentTask(MessageText.getString("wizard.webseed.adding"));
Map ws = wizard.webseeds;
List getright = (List)ws.get( "getright" );
if ( getright.size() > 0 ){
for (int i=0;i<getright.size();i++){
reportCurrentTask( " GetRight: " + getright.get(i));
}
torrent.setAdditionalListProperty( "url-list", new ArrayList( getright ));
}
List webseed = (List)ws.get( "webseed" );
if ( webseed.size() > 0 ){
for (int i=0;i<webseed.size();i++){
reportCurrentTask( " WebSeed: " + webseed.get(i));
}
torrent.setAdditionalListProperty( "httpseeds", new ArrayList( webseed ));
}
}
// must do this last as it saves a copy of the torrent state for future opening...
/*
* actually, don't need to do this as the "open-for-seeding" option used when adding the download
* does the job. Reason I stopped doing this is
* https://sourceforge.net/tracker/index.php?func=detail&aid=1721917&group_id=84122&atid=575154
*
DownloadManagerState download_manager_state =
DownloadManagerStateFactory.getDownloadState( torrent );
TorrentUtils.setResumeDataCompletelyValid( download_manager_state );
download_manager_state.save();
*/
this.reportCurrentTask(MessageText.getString("wizard.savingfile"));
final File torrent_file = new File(wizard.savePath);
torrent.serialiseToBEncodedFile(torrent_file);
this.reportCurrentTask(MessageText.getString("wizard.filesaved"));
wizard.switchToClose(
new Runnable()
{
public void
run()
{
show_torrent_file.setEnabled( true );
}
});
if ( wizard.autoOpen ){
CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD,
new AzureusCoreRunningListener() {
public void azureusCoreRunning(AzureusCore core) {
boolean start_stopped = COConfigurationManager.getBooleanParameter("Default Start Torrents Stopped");
byte[] hash = null;
try {
hash = torrent.getHash();
} catch (TOTorrentException e1) {
}
if ( wizard.forceStart || wizard.superseed ){
// superseeding can only be set for an active download...
start_stopped = false;
}
DownloadManagerInitialisationAdapter dmia;
final String initialTags = wizard.getInitialTags( true );
if ( initialTags.length() > 0 ){
dmia =
new DownloadManagerInitialisationAdapter()
{
public int
getActions()
{
return( ACT_ASSIGNS_TAGS );
}
public void
initialised(
DownloadManager dm,
boolean for_seeding )
{
TagManager tm = TagManagerFactory.getTagManager();
TagType tag_type = tm.getTagType( TagType.TT_DOWNLOAD_MANUAL );
String[] bits = initialTags.replace( ';', ',' ).split( "," );
for ( String tag: bits ){
tag = tag.trim();
if ( tag.length() > 0 ){
try{
Tag t = tag_type.getTag( tag, true );
if ( t == null ){
t = tag_type.createTag( tag, true );
}
t.addTaggable( dm );
}catch( Throwable e ){
Debug.out( e );
}
}
}
}
};
}else{
dmia = null;
}
final DownloadManager dm = core.getGlobalManager().addDownloadManager(
torrent_file.toString(),
hash,
save_dir.toString(),
start_stopped ? DownloadManager.STATE_STOPPED
: DownloadManager.STATE_QUEUED, true, // persistent
true, // for seeding
dmia );
if (!start_stopped && dm != null) {
// We want this to move to seeding ASAP, so move it to the top
// of the download list, where it will do the quick check and
// move to the seeding list
// (the for seeding flag should really be smarter and verify
// it's a seeding torrent and set appropriately)
dm.getGlobalManager().moveTop(new DownloadManager[] {
dm
});
}
if (wizard.autoHost
&& wizard.getTrackerType() != NewTorrentWizard.TT_EXTERNAL) {
try {
core.getTrackerHost().hostTorrent(torrent, true, false);
} catch (TRHostException e) {
Logger.log(new LogAlert(LogAlert.REPEATABLE,
"Host operation fails", e));
}
}
if ( dm != null ){
if ( wizard.forceStart ){
dm.setForceStart( true );
}
if ( wizard.superseed ){
new AEThread2( "startwait" )
{
public void
run()
{
long start = SystemTime.getMonotonousTime();
while( true ){
if ( dm.isDestroyed()){
break;
}
long elapsed = SystemTime.getMonotonousTime() - start;
if ( elapsed > 60*1000 ){
int state = dm.getState();
if ( state == DownloadManager.STATE_ERROR ||
state ==DownloadManager.STATE_STOPPED ){
break;
}
}
if ( elapsed > 5*60*1000 ){
break;
}
PEPeerManager pm = dm.getPeerManager();
if ( pm != null ){
pm.setSuperSeedMode( true );
break;
}
try{
Thread.sleep(1000);
}catch( Throwable e ){
break;
}
}
}
}.start();
}
}
}
});
}
}
catch (Exception e) {
if ( e instanceof TOTorrentException ){
TOTorrentException te = (TOTorrentException)e;
if ( te.getReason() == TOTorrentException.RT_CANCELLED ){
//expected failure, don't log exception
}else{
reportCurrentTask(MessageText.getString("wizard.operationfailed"));
reportCurrentTask( TorrentUtils.exceptionToText( te ));
}
}else{
Debug.printStackTrace( e );
reportCurrentTask(MessageText.getString("wizard.operationfailed"));
reportCurrentTask(Debug.getStackTrace(e));
}
wizard.switchToClose();
}
}
/* (non-Javadoc)
* @see org.gudy.azureus2.core3.torrent.TOTorrentProgressListener#reportCurrentTask(java.lang.String)
*/
public void reportCurrentTask(final String task_description) {
if (display != null && !display.isDisposed()) {
display.asyncExec(new AERunnable(){
public void runSupport() {
if (tasks != null && !tasks.isDisposed()) {
tasks.append(task_description + Text.DELIMITER);
}
}
});
}
}
/* (non-Javadoc)
* @see org.gudy.azureus2.core3.torrent.TOTorrentProgressListener#reportProgress(int)
*/
public void reportProgress(final int percent_complete) {
if (display != null && !display.isDisposed()) {
display.asyncExec(new AERunnable() {
public void runSupport() {
if (progress != null && !progress.isDisposed()) {
progress.setSelection(percent_complete);
}
}
});
}
}
}