ws.moor.bt.BitThief.java Source code

Java tutorial

Introduction

Here is the source code for ws.moor.bt.BitThief.java

Source

/*
 * BitThief - A Free Riding BitTorrent Client
 * Copyright (C) 2006 Patrick Moor <patrick@moor.ws>
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 * USA.
 */

package ws.moor.bt;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import ws.moor.bt.downloader.TorrentDownload;
import ws.moor.bt.downloader.TorrentDownloadConfiguration;
import ws.moor.bt.gui.BitThiefGUI;
import ws.moor.bt.torrent.MetaInfo;
import ws.moor.bt.torrent.MetaInfoBuilder;
import ws.moor.bt.util.LoggingUtil;
import ws.moor.bt.util.StringUtil;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Properties;

public class BitThief {

    private static final String METAFILE_OPTION = "m";
    private static final String OUTPUTDIR_OPTION = "o";
    private static final String PORT_OPTION = "p";
    private static final String GUI_OPTION = "g";
    private static final String NOSEEDS_OPTION = "n";
    private static final String NOINITIATE_OPTION = "i";
    private static final String HONESTBITFIELD_OPTION = "b";
    private static final String ANNOUNCEINTERVAL_OPTION = "a";
    private static final String SHARERATIO_OPTION = "s";
    private static final String QUITONFINISH_OPTION = "q";
    private static final String BITFIELDPERCENT_OPTION = "f";
    private static final String DOUPLOAD_OPTION = "u";
    private static final String UPLOADREAL_OPTION = "r";
    private static final String HELP_OPTION = "h";
    private static final String MAXUPLOAD_OPTION = "uploadrate";
    private static final String UPLOADSLOTS_OPTION = "uploadslots";
    private static final String DENYPERCENTAGE_OPTION = "denypercentage";

    private static final Logger logger = LoggingUtil.getLogger(BitThief.class);

    public static void main(String[] arguments) throws Exception {
        BitThiefConfiguration bitThiefConfiguration = loadBitThiefConfiguration();
        configureStaticStuff(bitThiefConfiguration);

        CommandLine line = parseCommandLine(arguments);

        logger.info("BitThief " + Version.getLongVersionString());
        logArguments(arguments);

        logger.info("setting up environment");
        Environment environment = new Environment(bitThiefConfiguration);

        boolean showGui = true;
        if (line.hasOption(METAFILE_OPTION) && line.hasOption(OUTPUTDIR_OPTION)) {
            File torrentFile = new File(line.getOptionValue(METAFILE_OPTION));
            File targetDirectory = new File(line.getOptionValue(OUTPUTDIR_OPTION));

            logger.info("reading meta info file " + torrentFile);
            MetaInfo metaInfo = MetaInfoBuilder.fromFile(torrentFile);

            TorrentDownloadConfiguration configuration = new TorrentDownloadConfiguration(metaInfo,
                    targetDirectory);
            initConfiguration(configuration, line);

            logger.info("creating torrent download");
            TorrentDownload download = new TorrentDownload(environment, configuration);

            logger.info("starting torrent download");
            download.start();

            showGui = configuration.showGui();
        }

        if (showGui) {
            logger.info("starting GUI");
            BitThiefGUI gui = new BitThiefGUI(environment);
            gui.show();
        }
    }

    private static void configureStaticStuff(BitThiefConfiguration configuration) throws IOException {
        InputStream stream = ClassLoader.getSystemResourceAsStream(configuration.getLoggingPropertyFile());
        if (stream != null) {
            Properties properties = new Properties();
            properties.load(stream);
            PropertyConfigurator.configure(properties);
        } else {
            System.err.println("unable to load logging property file");
            System.exit(1);
        }
    }

    private static BitThiefConfiguration loadBitThiefConfiguration() {
        BitThiefConfiguration configuration = BitThiefConfiguration.fromPropertiesFile();
        if (configuration == null) {
            System.err.println("Error loading property file.");
            System.exit(1);
        }
        return configuration;
    }

    private static void logArguments(String[] arguments) {
        StringBuilder commandLine = new StringBuilder();
        commandLine.append("Arguments: ");
        commandLine.append(StringUtil.join(Arrays.asList(arguments), " "));
        logger.info(commandLine.toString());
    }

    private static void initConfiguration(TorrentDownloadConfiguration configuration, CommandLine line) {
        if (line.hasOption(PORT_OPTION)) {
            configuration.setListeningPort(Integer.parseInt(line.getOptionValue(PORT_OPTION)));
        }
        if (line.hasOption(ANNOUNCEINTERVAL_OPTION)) {
            configuration
                    .setInitialAnnounceInterval(Integer.parseInt(line.getOptionValue(ANNOUNCEINTERVAL_OPTION)));
        }
        if (line.hasOption(SHARERATIO_OPTION)) {
            configuration.setShareRatio(Double.parseDouble(line.getOptionValue(SHARERATIO_OPTION)));
        }
        if (line.hasOption(MAXUPLOAD_OPTION)) {
            configuration.setMaxUploadRate(Integer.parseInt(line.getOptionValue(MAXUPLOAD_OPTION)));
        }
        if (line.hasOption(BITFIELDPERCENT_OPTION)) {
            configuration.setBitfieldPercent(Integer.parseInt(line.getOptionValue(BITFIELDPERCENT_OPTION)));
        }
        if (line.hasOption(UPLOADSLOTS_OPTION)) {
            configuration.setUploadSlots(Integer.parseInt(line.getOptionValue(UPLOADSLOTS_OPTION)));
        }
        if (line.hasOption(DENYPERCENTAGE_OPTION)) {
            configuration
                    .setPieceUploadDenyPercentage(Integer.parseInt(line.getOptionValue(DENYPERCENTAGE_OPTION)));
        }
        configuration.setShowGui(line.hasOption(GUI_OPTION));
        configuration.setDownloadFromSeeders(!line.hasOption(NOSEEDS_OPTION));
        configuration.setInitiateConnections(!line.hasOption(NOINITIATE_OPTION));
        configuration.setSendRealBitField(line.hasOption(HONESTBITFIELD_OPTION));
        configuration.setQuitOnFinish(line.hasOption(QUITONFINISH_OPTION));
        configuration.setUploadRealData(line.hasOption(UPLOADREAL_OPTION));
        configuration.setUploading(line.hasOption(DOUPLOAD_OPTION));
    }

    private static CommandLine parseCommandLine(String[] args) {
        CommandLineParser parser = new GnuParser();
        Options options = createOptions();

        try {
            CommandLine commandLine = parser.parse(options, args, true);
            if (commandLine.hasOption(HELP_OPTION)) {
                printHelpTextAndExit(options);
            }
            return commandLine;
        } catch (ParseException e) {
            printHelpTextAndExit(options);
        }
        return null;
    }

    private static void printHelpTextAndExit(Options options) {
        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp("BitThief", options, true);
        System.exit(1);
    }

    private static Options createOptions() {
        Options options = new Options();
        options.addOption(OptionBuilder.withLongOpt("metafile").withDescription("meta file").withArgName("file")
                .hasArg().create(METAFILE_OPTION));
        options.addOption(OptionBuilder.withLongOpt("output").withDescription("output directory")
                .withArgName("directory").hasArg().create(OUTPUTDIR_OPTION));
        options.addOption(OptionBuilder.withLongOpt("port")
                .withDescription(
                        "listening port (default: " + TorrentDownloadConfiguration.DEFAULT_LISTENING_PORT + ")")
                .withArgName("port").hasArg().create(PORT_OPTION));
        options.addOption(OptionBuilder.withLongOpt("gui").withDescription("show gui").create(GUI_OPTION));
        options.addOption(OptionBuilder.withLongOpt("noseeds").withDescription("do not leech from seeds")
                .create(NOSEEDS_OPTION));
        options.addOption(OptionBuilder.withLongOpt("noinitiate")
                .withDescription("do not initiate outgoing connections").create(NOINITIATE_OPTION));
        options.addOption(OptionBuilder.withLongOpt("honestbitfield")
                .withDescription("send real bit field (default: send empty field)").create(HONESTBITFIELD_OPTION));
        options.addOption(OptionBuilder.withLongOpt("bitfieldpercent")
                .withDescription("percent of pieces to set in bitfield (default: "
                        + TorrentDownloadConfiguration.DEFAULT_BITFIELD_PERCENT + ")")
                .withArgName("%").hasArg().create(BITFIELDPERCENT_OPTION));
        options.addOption(OptionBuilder.withLongOpt("announceinterval")
                .withDescription("initial announce interval (default: "
                        + TorrentDownloadConfiguration.DEFAULT_ANNOUNCE_INTERVAL + ")")
                .withArgName("seconds").hasArg().create(ANNOUNCEINTERVAL_OPTION));
        options.addOption(OptionBuilder.withLongOpt("shareratio")
                .withDescription(
                        "share ratio to fake (default: " + TorrentDownloadConfiguration.DEFAULT_SHARE_RATIO + ")")
                .withArgName("ratio").hasArg().create(SHARERATIO_OPTION));
        options.addOption(OptionBuilder.withLongOpt("quitonfinish").withDescription("quit on finish")
                .create(QUITONFINISH_OPTION));
        options.addOption(OptionBuilder
                .withDescription("max data upload rate (default: "
                        + TorrentDownloadConfiguration.DEFAULT_MAX_UPLOAD_RATE + ")")
                .withArgName("KB/s").hasArg().create(MAXUPLOAD_OPTION));
        options.addOption(OptionBuilder.withLongOpt("uploadreal").withDescription("do upload real data")
                .create(UPLOADREAL_OPTION));
        options.addOption(OptionBuilder
                .withDescription("number of upload slots (default: "
                        + TorrentDownloadConfiguration.DEFAULT_UPLOAD_SLOTS + ")")
                .withArgName("slots").hasArg().create(UPLOADSLOTS_OPTION));
        options.addOption(OptionBuilder.withLongOpt("upload")
                .withDescription(
                        "do upload (default: " + TorrentDownloadConfiguration.DEFAULT_UPLOADING_STATUS + ")")
                .create(DOUPLOAD_OPTION));
        options.addOption(OptionBuilder
                .withDescription("percentage of pieces to deny for uploading (default: "
                        + TorrentDownloadConfiguration.DEFAULT_PIECE_UPLOAD_DENY_PERCENTAGE + ")")
                .withArgName("%").hasArg().create(DENYPERCENTAGE_OPTION));
        options.addOption(
                OptionBuilder.withDescription("display this help text").withLongOpt("help").create(HELP_OPTION));
        return options;
    }
}