Package com.torrent4j.model

Source Code of com.torrent4j.model.Torrent

package com.torrent4j.model;

import static com.torrent4j.util.HashType.MD5;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.torrent4j.TorrentController;
import com.torrent4j.model.metadata.MetadataFile;
import com.torrent4j.model.metadata.MetadataInfo;
import com.torrent4j.model.metadata.TorrentMetadata;
import com.torrent4j.net.TorrentProtocol;
import com.torrent4j.strategy.TorrentStrategy;
import com.torrent4j.strategy.standard.StandardTorrentStrategy;
import com.torrent4j.util.Range;
import com.torrent4j.util.bencoding.BDecoder;
import com.torrent4j.util.bencoding.BMap;

/**
* The main Torrent instance class. With this class, all torrent state is stored
* and external interaction can be performed.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class Torrent {
  /**
   * The torrent strategy
   */
  private final TorrentStrategy strategy;

  /**
   * The torrent meta data
   */
  private final TorrentMetadata metadata;
  /**
   * The torrent hash
   */
  private final TorrentHash hash;

  /**
   * The torrent pieces
   */
  private final List<TorrentPiece> pieces = new ArrayList<>();
  /**
   * The torrent files
   */
  private final List<TorrentFile> files = new ArrayList<>();

  /**
   * The torrent traffic control
   */
  private final TorrentTrafficControl trafficControl = new TorrentTrafficControl(this);
  /**
   * The torrent swarm (list of all peers)
   */
  private final TorrentSwarm swarm = new TorrentSwarm(this);
  /**
   * The torrent already downloaded pieces
   */
  private final TorrentCompletePieces completedPieces;

  /**
   * The current controller for this torrent object. If not attached to any
   * controller, its value is <code>null</code>.
   */
  private TorrentController controller;

  /**
   * Creates a new torrent instance
   *
   * @param strategy
   *            the torrent strategy
   * @param metadata
   *            the torrent meta data
   */
  public Torrent(TorrentStrategy strategy, TorrentMetadata metadata) {
    this.strategy = strategy;
    this.metadata = metadata;
    this.hash = new TorrentHash(this, metadata.getInfoHash());

    // parse file list
    final MetadataInfo info = metadata.getInfo();
    final byte[] pieceHashes = info.getPieceHashes();
    final int pieces = pieceHashes.length / 20;
    long piecesLength = 0;
    for (int i = 0; i < pieces; i++) {
      final byte[] hash = Arrays.copyOfRange(pieceHashes, i * 20,
          (i + 1) * 20);
      final int length = (int) (i + 1 == pieces ? (info.getLength() - piecesLength)
          : info.getPieceLength());

      this.pieces.add(new TorrentPiece(this, hash, i, info
          .getPieceLength() * i, length));
      piecesLength += length;
    }

    final Path torrentPath = Paths.get(info.getName());
    long offset = 0;
    for (final MetadataFile metaFile : info.getFiles()) {
      byte[] hash = null;
      if (metaFile.getHash() != null)
        hash = MD5.fromString(metaFile.getHash());
      final List<TorrentPiece> filePieces = getPieces(Range
          .getRangeByLength(offset, metaFile.getLength()));
      final TorrentFile file = new TorrentFile(this, offset,
          metaFile.getLength(), filePieces,
          torrentPath.resolve(metaFile.getFileName()), hash);
      files.add(file);
      for (final TorrentPiece piece : filePieces) {
        piece.addFile(file);
      }
      offset += metaFile.getLength();
    }

    completedPieces = new TorrentCompletePieces(this);

    // try {
    // this.localPeer.setPeerID(new String(Hex
    // .decodeHex("851054102530302d9c640cd409c769266ad3a04f"
    // .toCharArray())));
    // } catch (DecoderException e) {
    // }
  }

  /**
   * Creates a new torrent instance with {@link StandardTorrentStrategy} as
   * default strategy
   *
   * @param metadata
   *            the torrent meta data
   */
  public Torrent(TorrentMetadata metadata) {
    this(new StandardTorrentStrategy(), metadata);
  }

  /**
   * @return this torrent's strategy
   */
  public TorrentStrategy getStrategy() {
    return strategy;
  }

  /**
   * @return this torrent's meta data
   */
  public TorrentMetadata getMetadata() {
    return metadata;
  }

  /**
   * @return this torrent's hash
   */
  public TorrentHash getHash() {
    return hash;
  }

  /**
   * @return this torrent's pieces
   */
  public List<TorrentPiece> getPieces() {
    return pieces;
  }

  /**
   * Determines all the pieces that contains at least one byte inside the
   * requested range.
   *
   * @param range
   *            the range to look for pieces
   * @return the pieces inside the requested <code>range</code>
   */
  public List<TorrentPiece> getPieces(Range range) {
    final List<TorrentPiece> pieces = new ArrayList<>();
    for (final TorrentPiece piece : this.pieces) {
      if (piece.getTorrentRange().intersects(range))
        pieces.add(piece);
    }
    return pieces;
  }

  /**
   * @param index
   *            the piece index
   * @return the piece at the requested index, if any.
   */
  public TorrentPiece getPiece(int index) {
    if ((index + 1) > pieces.size())
      return null;
    return pieces.get(index);
  }

  /**
   * @return all the files for this torrent
   */
  public List<TorrentFile> getFiles() {
    return files;
  }

  /**
   * Determines all the files that contains at least one byte inside the
   * requested range.
   *
   * @param range
   *            the range to search for files
   * @return the list of files inside the requested <code>range</code>
   */
  public List<TorrentFile> getFiles(Range range) {
    final List<TorrentFile> files = new ArrayList<>();
    for (final TorrentFile file : this.files) {
      if (file.getTorrentRange().intersects(range))
        files.add(file);
    }
    return files;
  }

  /**
   * @return the sum of all file sizes
   */
  public long getTorrentSize() {
    long size = 0;
    for (final TorrentFile file : files) {
      size += file.getLength();
    }
    return size;
  }

  /**
   * @return the trafficControl
   */
  public TorrentTrafficControl getTrafficControl() {
    return trafficControl;
  }

  /**
   * @return the torrent swarm
   */
  public TorrentSwarm getSwarm() {
    return swarm;
  }

  /**
   * @return the downloaded pieces
   */
  public TorrentCompletePieces getCompletedPieces() {
    return completedPieces;
  }

  /**
   * @return this torrent's controller, if any.
   */
  public TorrentController getController() {
    return controller;
  }

  /**
   * Sets the current controller. <b>This method should not be invoked
   * manually!</b>
   *
   * @param controller
   *            the controller to set
   */
  public void setController(TorrentController controller) {
    this.controller = controller;
  }

  /**
   * @return the torrent protocol
   */
  public TorrentProtocol getProtocol() {
    return controller.getProtocol();
  }

  @Override
  public String toString() {
    return "Torrent [hash=" + hash + "]";
  }

  /**
   * Load an torrent from an {@link InputStream}
   *
   * @param in
   *            the {@link InputStream}
   * @return the loaded {@link Torrent} instance
   * @throws IOException
   *             if any error occur while reading the torrent file
   */
  public static Torrent load(InputStream in) throws IOException {
    final Object node = new BDecoder(in).readElement();
    final TorrentMetadata metadata = new TorrentMetadata((BMap) node);
    return new Torrent(metadata);
  }

  /**
   * Load an torrent from an {@link InputStream}
   *
   * @param file
   *            the file {@link Path}
   * @return the loaded {@link Torrent} instance
   * @throws IOException
   *             if any error occur while reading the torrent file
   */
  public static Torrent load(Path file) throws IOException {
    return load(Files.newInputStream(file));
  }

  /**
   * Load an torrent from an {@link File}
   *
   * @param file
   *            the {@link File}
   * @return the loaded {@link Torrent} instance
   * @throws IOException
   *             if any error occur while reading the torrent file
   */
  public static Torrent load(File file) throws IOException {
    if (file == null)
      throw new InvalidParameterException("File cannot be null");
    return load(new FileInputStream(file));
  }

  /**
   * Load an torrent from an {@link Byte} array
   *
   * @param content
   *            the {@link Byte} array
   * @return the loaded {@link Torrent} instance
   * @throws IOException
   *             if any error occur while reading the torrent file
   */
  public static Torrent load(byte[] content) throws IOException {
    return load(new ByteArrayInputStream(content));
  }

  /**
   * Load an torrent from an {@link File}
   *
   * @param url
   *            the {@link URL}
   * @return the loaded {@link Torrent} instance
   * @throws IOException
   *             if any error occur while reading the torrent file
   */
  public static Torrent load(URL url) throws IOException {
    if (url == null)
      throw new InvalidParameterException("File cannot be null");
    return load(url.openStream());
  }
}
TOP

Related Classes of com.torrent4j.model.Torrent

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.