/**
  * Build the URL of the Vuze XML over HTTP plugin listener from the user settings.
  *
  * @return The URL of the RPC API
  */
 private String buildWebUIUrl() {
   return (settings.getSsl() ? "https://" : "http://")
       + settings.getAddress()
       + ":"
       + settings.getPort()
       + RPC_URL;
 }
 /**
  * Build the URL of the Transmission web UI from the user settings.
  *
  * @return The URL of the RPC API
  */
 private String buildWebUIUrl() {
   String webuiroot = "";
   if (settings.getFolder() != null) {
     webuiroot = settings.getFolder();
   }
   return (settings.getSsl() ? "https://" : "http://")
       + settings.getAddress()
       + ":"
       + settings.getPort()
       + webuiroot
       + "/";
 }
 /**
  * Creates a standard Apache HttpClient that is thread safe, supports different SSL auth methods
  * and basic authentication
  *
  * @param settings The server settings to adhere
  * @return An HttpClient that should be stored locally and reused for every new request
  * @throws DaemonException Thrown when information (such as username/password) is missing
  */
 public static DefaultHttpClient createStandardHttpClient(
     DaemonSettings settings, boolean userBasicAuth) throws DaemonException {
   return createStandardHttpClient(
       userBasicAuth && settings.shouldUseAuthentication(),
       settings.getUsername(),
       settings.getPassword(),
       settings.getSslTrustAll(),
       settings.getSslTrustKey(),
       settings.getTimeoutInMilliseconds(),
       settings.getAddress(),
       settings.getPort());
 }
  private synchronized Map<String, Object> makeVuzeCall(
      DaemonMethod method,
      String serverMethod,
      Long actOnObject,
      Object[] params,
      TorrentStatus torrentStatus)
      throws DaemonException {

    // TODO: It would be nicer to now split each of these steps into separate makeVuzeCalls when
    // there are multiple logical steps such as stopping a torrent before removing it

    // Initialise the HTTP client
    if (rpcclient == null) {
      initialise();
    }
    if (settings.getAddress() == null || settings.getAddress().equals("")) {
      throw new DaemonException(
          DaemonException.ExceptionType.AuthenticationFailure, "No host name specified.");
    }

    if (savedConnectionID == null || savedPluginID == null) {
      // Get plug-in interface (for connection and plug-in object IDs)
      Map<String, Object> plugin = rpcclient.callXMLRPC(null, "getSingleton", null, null, false);
      if (!plugin.containsKey("_connection_id")) {
        throw new DaemonException(
            ExceptionType.UnexpectedResponse, "No connection ID returned on getSingleton request.");
      }
      savedConnectionID = (Long) plugin.get("_connection_id");
      savedPluginID = (Long) plugin.get("_object_id");
    }

    // If no specific torrent was provided, get the download manager or plugin config to execute the
    // method against
    long vuzeObjectID;
    if (actOnObject == null) {
      if (method == DaemonMethod.SetTransferRates) {

        // Execute this method against the plugin config (setParameter)
        if (savedPluginConfigID == null) {
          // Plugin config needed, but we don't know it's ID yet
          Map<String, Object> config =
              rpcclient.callXMLRPC(
                  savedPluginID, "getPluginconfig", null, savedConnectionID, false);
          if (!config.containsKey("_object_id")) {
            throw new DaemonException(
                ExceptionType.UnexpectedResponse,
                "No plugin config ID returned on getPluginconfig");
          }
          savedPluginConfigID = (Long) config.get("_object_id");
          vuzeObjectID = savedPluginConfigID;
        } else {
          // We stored the plugin config ID, so no need to ask for it again
          vuzeObjectID = savedPluginConfigID;
        }

      } else if (serverMethod.equals("createFromBEncodedData[byte[]]")) {

        // Execute this method against the torrent manager (createFromBEncodedData)
        if (savedTorrentManagerID == null) {
          // Download manager needed, but we don't know it's ID yet
          Map<String, Object> manager =
              rpcclient.callXMLRPC(
                  savedPluginID, "getTorrentManager", null, savedConnectionID, false);
          if (!manager.containsKey("_object_id")) {
            throw new DaemonException(
                ExceptionType.UnexpectedResponse,
                "No torrent manager ID returned on getTorrentManager");
          }
          savedTorrentManagerID = (Long) manager.get("_object_id");
          vuzeObjectID = savedTorrentManagerID;
        } else {
          // We stored the torrent manager ID, so no need to ask for it again
          vuzeObjectID = savedTorrentManagerID;
        }
        // And we will need the download manager as well later on (for addDownload after
        // createFromBEncodedData)
        if (savedDownloadManagerID == null) {
          // Download manager needed, but we don't know it's ID yet
          Map<String, Object> manager =
              rpcclient.callXMLRPC(
                  savedPluginID, "getDownloadManager", null, savedConnectionID, false);
          if (!manager.containsKey("_object_id")) {
            throw new DaemonException(
                ExceptionType.UnexpectedResponse,
                "No download manager ID returned on getDownloadManager");
          }
          savedDownloadManagerID = (Long) manager.get("_object_id");
        }

      } else {

        // Execute this method against download manager (addDownload, startAllDownloads, etc.)
        if (savedDownloadManagerID == null) {
          // Download manager needed, but we don't know it's ID yet
          Map<String, Object> manager =
              rpcclient.callXMLRPC(
                  savedPluginID, "getDownloadManager", null, savedConnectionID, false);
          if (!manager.containsKey("_object_id")) {
            throw new DaemonException(
                ExceptionType.UnexpectedResponse,
                "No download manager ID returned on getDownloadManager");
          }
          savedDownloadManagerID = (Long) manager.get("_object_id");
          vuzeObjectID = savedDownloadManagerID;
        } else {
          // We stored the download manager ID, so no need to ask for it again
          vuzeObjectID = savedDownloadManagerID;
        }
      }
    } else {
      vuzeObjectID = actOnObject;
    }

    if (method == DaemonMethod.Remove
        && torrentStatus != null
        && torrentStatus != TorrentStatus.Paused) {
      // Vuze, for some strange reason, wants us to stop the torrent first before removing it
      rpcclient.callXMLRPC(vuzeObjectID, "stop", new Object[] {}, savedConnectionID, false);
    }

    boolean paramsAreVuzeObjects = false;
    if (serverMethod.equals("createFromBEncodedData[byte[]]")) {
      // Vuze does not directly add the torrent that we are uploading the file contents of
      // We first do the createFromBEncodedData call and next actually add it
      Map<String, Object> torrentData =
          rpcclient.callXMLRPC(vuzeObjectID, serverMethod, params, savedConnectionID, false);
      serverMethod = "addDownload[Torrent]";
      vuzeObjectID = savedDownloadManagerID;
      params = new String[] {((Long) torrentData.get("_object_id")).toString()};
      paramsAreVuzeObjects = true;
    }

    // Call the actual method we wanted
    return rpcclient.callXMLRPC(
        vuzeObjectID, serverMethod, params, savedConnectionID, paramsAreVuzeObjects);
  }