/*
* Written and copyright 2001-2003 Tobias Minich. Distributed under the GNU
* General Public License; see the README file. This code comes with NO
* WARRANTY.
*
* AddFind.java
*
* Created on 23.03.2004
*
*/
package org.gudy.azureus2.ui.console.commands;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.OptionBuilder;
import org.gudy.azureus2.ui.console.ConsoleInput;
import org.pf.file.FileFinder;
import org.pf.text.StringUtil;
import com.aelitis.azureus.core.AzureusCoreException;
/**
* this class allows the user to add and find torrents.
* when adding, you may specify an output directory
* when finding, it will cache the files it finds into the ConsoleInput object
* so that they can then be added by id
* @author tobi, fatal
*/
public class AddFind extends OptionsConsoleCommand {
public AddFind()
{
super("add", "a");
OptionBuilder.withArgName("outputDir");
OptionBuilder.withLongOpt("output");
OptionBuilder.hasArg();
OptionBuilder.withDescription("override default download directory");
OptionBuilder.withType(File.class);
getOptions().addOption( OptionBuilder.create('o') );
getOptions().addOption("r", "recurse", false, "recurse sub-directories.");
getOptions().addOption("f", "find", false, "only find files, don't add.");
getOptions().addOption("h", "help", false, "display help about this command");
getOptions().addOption("l", "list", false, "list previous find results");
}
public String getCommandDescriptions()
{
return "add [addoptions] [.torrent path|url]\t\ta\tAdd a download from the given .torrent file path or url. Example: 'add /path/to/the.torrent' or 'add http://www.url.com/to/the.torrent'";
}
public void execute(String commandName, ConsoleInput ci, CommandLine commands)
{
if( commands.hasOption('l') )
{
ci.out.println("> -----");
showAdds(ci);
ci.out.println("> -----");
return;
}
else if( commands.hasOption('h') || commands.getArgs().length == 0 )
{
printHelp(ci.out, (String)null);
return;
}
String outputDir = ".";
if (commands.hasOption('o'))
outputDir = commands.getOptionValue('o');
else
outputDir = ci.getDefaultSaveDirectory();
File f = new File(outputDir);
if( ! f.isAbsolute() )
{
// make it relative to current directory
try {
outputDir = new File(".", outputDir).getCanonicalPath();
} catch (IOException e) {
throw new AzureusCoreException("exception occurred while converting directory: ./" + outputDir + " to its canonical path");
}
}
boolean scansubdir = commands.hasOption('r');
boolean finding = commands.hasOption('f');
String[] whatelse = commands.getArgs();
for (int i = 0; i < whatelse.length; i++) {
String arg = whatelse[i];
try {
// firstly check if it is a valid URL
new URL(arg);
addRemote(ci, arg, outputDir);
} catch (MalformedURLException e)
{
// assume that it's a local file or file id from a previous find
addLocal(ci, arg, outputDir, scansubdir, finding);
}
}
}
/**
* attempt to download the torrent specified by 'arg' and save the files
* in the torrent to the specified output directory
* @param ci
* @param arg URL of torrent to download
* @param outputDir directory to save files from torrent to
*/
protected void addRemote(ConsoleInput ci, String arg, String outputDir) {
ci.out.println("> Starting Download of " + arg + " ...");
try {
ci.downloadRemoteTorrent(arg, outputDir);
} catch (Exception e) {
ci.out.println("An error occurred while downloading torrent: " + e.getMessage());
e.printStackTrace(ci.out);
}
}
/**
* attempt a local add (arg may be a directory, a file or a pattern eg: d:/*.torrent)
* @param ci
* @param arg argument - could be directory, file or pattern eg: d:\*.torrent
* @param outputDir directory to save files from torrent to
* @param scansubdir if true, will recurse subdirectories looking for files to add
* @param finding if true, don't start downloading the files; simply add them to the 'found' list
*/
protected void addLocal(ConsoleInput ci, String arg, String outputDir, boolean scansubdir, boolean finding)
{
// substitute ~ for home directory, if specified
arg = transformLocalArgument(arg);
// see if the argument is an existing file or directory
File test = new File(arg);
if (test.exists()) {
if (test.isDirectory()) {
File[] toadd = FileFinder.findFiles(arg, "*.torrent;*.tor", scansubdir);
if ((toadd != null) && (toadd.length > 0)) {
addFiles( ci, toadd, finding, outputDir );
} else {
ci.adds = null;
ci.out.println("> Directory '" + arg + "' seems to contain no torrent files.");
}
} else {
ci.downloadTorrent(arg, outputDir);
ci.out.println("> '" + arg + "' added.");
ci.torrents.clear();
}
return;
}
// check to see if they are numeric and if so, try and add them from the 'adds' in ci
try {
int id = Integer.parseInt(arg);
if( ci.adds != null && ci.adds.length > id )
{
String torrentPath = ci.adds[id].getAbsolutePath();
ci.downloadTorrent(torrentPath, outputDir);
ci.out.println("> '" + torrentPath + "' added.");
ci.torrents.clear();
}
else
{
ci.out.println("> No such file id '" + id + "'. Try \"add -l\" to list available files");
}
return;
} catch (NumberFormatException e)
{
}
// last resort - try to process it as a directory/pattern eg: c:/torrents/*.torrent
String dirName = test.getParent();
if( dirName == null )
dirName = ".";
String filePattern = test.getName();
File []files = FileFinder.findFiles(dirName, filePattern, false);
if ((files != null) && (files.length > 0)) {
addFiles(ci, files, finding, outputDir );
} else {
ci.adds = null;
ci.out.println("> No files found. Searched for '" + filePattern + "' in '" + dirName + "'");
}
}
/**
* perform any transformations on the argument - in this case we are
* replacing '~' with the user's home directory.
* @param arg
* @return
*/
protected String transformLocalArgument(String arg) {
if( arg.startsWith("~/") || arg.equals("~") )
{
arg = StringUtil.current().replaceAll(arg, "~", System.getProperty("user.home"));
}
return arg;
}
/**
* if finding is set, just print the available files and add them to the 'add' list inside the consoleinput object,
* otherwise actually add the torrents, saving to the specified output directory
* @param toadd
* @param finding
* @param outputDir
*/
protected void addFiles(ConsoleInput ci, File[] toadd, boolean finding, String outputDir) {
ci.out.println("> -----");
ci.out.println("> Found " + toadd.length + " files:");
if( finding )
{
ci.adds = toadd;
showAdds(ci);
}
else
{
for (int i = 0; i < toadd.length; i++) {
ci.downloadTorrent(toadd[i].getAbsolutePath(), outputDir);
ci.out.println("> '" + toadd[i].getAbsolutePath() + "' added.");
ci.torrents.clear();
}
}
ci.out.println("> -----");
}
/**
* prints out the files in the 'add' list that is stored in the console input object.
* @param ci
*/
private void showAdds(ConsoleInput ci) {
if( ci.adds == null || ci.adds.length == 0 )
{
ci.out.println("> No files found. Try \"add -f <path>\" first");
return;
}
for (int i = 0; i < ci.adds.length; i++) {
ci.out.print(">\t" + i + ":\t");
try {
ci.out.println(ci.adds[i].getCanonicalPath());
} catch (Exception e) {
ci.out.println(ci.adds[i].getAbsolutePath());
}
}
ci.out.println("> To add, simply type 'add <id>'");
}
}