/** Part of the ChecksumMover interface. */
  private ChecksumFactory getChecksumFactory(GFtpProtocolInfo protocol) {
    String type = protocol.getChecksumType();
    if (type == null || type.equals("Unknown")) {
      return null;
    }

    try {
      return ChecksumFactory.getFactory(ChecksumType.getChecksumType(type));
    } catch (NoSuchAlgorithmException e) {
      esay("CRC Algorithm is not supported: " + type);
    }

    return null;
  }
  /** Test program for this class. */
  public static void main(String a[]) {
    try {
      Args args = new Args(a);
      int port = Integer.valueOf(getOption(args, "port", "2288"));
      int bufferSize = Integer.valueOf(getOption(args, "buffer", "0"));
      int parallelism = Integer.valueOf(getOption(args, "streams", "1"));
      long offset = Long.valueOf(getOption(args, "offset", "0"));
      long size = Long.valueOf(getOption(args, "size", "0"));
      String digest = getOption(args, "digest", "");
      boolean verbose = Boolean.valueOf(getOption(args, "verbose", "false"));

      Role role = Role.Receiver;
      if (args.isOneCharOption('r')) {
        role = Role.Receiver;
      } else if (args.isOneCharOption('s')) {
        role = Role.Sender;
      } else {
        help();
      }

      GFtpProtocol_2_nio mover = new GFtpProtocol_2_nio(null);

      RepositoryChannel fileChannel =
          new FileRepositoryChannel(args.argv(0), role == Role.Sender ? "r" : "rw");

      Mode mode = mover.createMode(getOption(args, "mode", "S"), role, fileChannel);

      if (args.isOneCharOption('l')) {
        if (args.argc() != 1) {
          help();
        }
        ServerSocketChannel channel = ServerSocketChannel.open();
        if (bufferSize > 0) {
          channel.socket().setReceiveBufferSize(bufferSize);
        }
        channel.socket().bind(new InetSocketAddress(port));
        mode.setPassive(channel);
      } else {
        if (args.argc() != 2) {
          help();
        }
        mode.setActive(new InetSocketAddress(args.argv(1), port));
      }

      if (digest.length() > 0 && role != Role.Receiver) {
        System.err.println("Digest can only be computed on receive");
        System.exit(1);
      }

      if (size == 0) {
        size = fileChannel.size() - offset;
      }

      mode.setParallelism(parallelism);
      mode.setPartialRetrieveParameters(offset, size);

      if (digest.length() > 0) {
        mover.enableTransferChecksum(ChecksumType.getChecksumType(digest));
      }

      mover.setVerboseLogging(verbose);
      mover.transfer(fileChannel, role, mode, null);
      if (digest.length() > 0) {
        System.out.println(mover.getActualChecksum());
      }
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(1);
    }
  }