/** @param requiresAuthorization */
  protected static void processQueue(String queueID, Map mapQueue) {
    if (!initialized) {
      init();
    }

    final Map mapProcessing = new HashMap();

    boolean sendAZID = true;
    long contentNetworkID = ContentNetwork.CONTENT_NETWORK_VUZE;

    // Create urlStem (or post data)
    boolean isMulti = false;
    StringBuffer urlStem = new StringBuffer();
    long sequenceNo = 0;

    Map<String, Object> mapPayload = new HashMap<String, Object>();
    mapPayload.put("azid", ConstantsVuze.AZID);
    mapPayload.put("azv", Constants.AZUREUS_VERSION);
    // mapPayload.put("mode", FeatureManagerUI.getMode());
    mapPayload.putAll(mapExtra);
    List<Map> listCommands = new ArrayList<Map>();
    mapPayload.put("commands", listCommands);

    queue_mon.enter();
    try {
      String lastServer = null;
      // add one at a time, ensure relay server messages are seperate
      boolean first = true;
      for (Iterator iter = mapQueue.keySet().iterator(); iter.hasNext(); ) {
        PlatformMessage message = (PlatformMessage) iter.next();
        Object value = mapQueue.get(message);

        Map<String, Object> mapCmd = new HashMap<String, Object>();

        if (first) {
          sendAZID = message.sendAZID();
          contentNetworkID = message.getContentNetworkID();
          first = false;
        }

        // build urlStem
        message.setSequenceNo(sequenceNo);

        if (urlStem.length() > 0) {
          urlStem.append('&');
        }

        String listenerID = message.getListenerID();
        String messageID = message.getMessageID();
        Map params = message.getParameters();
        try {
          urlStem.append("msg=");
          urlStem.append(URLEncoder.encode(listenerID, "UTF-8"));
          urlStem.append(":");
          urlStem.append(URLEncoder.encode(message.getOperationID(), "UTF-8"));
        } catch (UnsupportedEncodingException e) {
        }

        mapCmd.put("seq-id", sequenceNo);
        mapCmd.put("listener-id", listenerID);
        mapCmd.put("op-id", message.getOperationID());
        if (params != null) {
          mapCmd.put("values", params);
        }
        listCommands.add(mapCmd);

        // We used to check on MAX_POST_LENGTH, but with the changes that
        // would require converting the map to JSON on every iteration to get
        // the length.  For now, just limit to 10
        if (sequenceNo > 10) {
          debug("breaking up batch at " + sequenceNo + " because max limit would be exceeded");
          break;
        }

        String curServer = messageID + "-" + listenerID;
        if (lastServer != null && !lastServer.equals(curServer)) {
          isMulti = true;
        }
        lastServer = curServer;

        PlatformMessengerListener listener = (PlatformMessengerListener) mapProcessing.get(message);
        if (listener != null) {
          listener.messageSent(message);
        }
        sequenceNo++;

        // Adjust lists
        mapProcessing.put(message, value);

        iter.remove();

        if (!getAllowMulti()) {
          break;
        }
      }
    } finally {
      queue_mon.exit();
    }
    // debug("about to process " + mapProcessing.size());

    if (mapProcessing.size() == 0) {
      return;
    }

    // Build base RPC url based on listener and server

    // one day all this URL hacking should be moved into the ContentNetwork...

    ContentNetwork cn =
        ContentNetworkManagerFactory.getSingleton().getContentNetwork(contentNetworkID);
    if (cn == null) {
      cn = ConstantsVuze.getDefaultContentNetwork();
    }

    String sURL_RPC =
        ContentNetworkUtils.getUrl(cn, ContentNetwork.SERVICE_RPC) + "&" + urlStem.toString();

    // Build full url and data to send
    String sURL;
    String sPostData = null;
    String sJSONPayload = UrlUtils.encode(JSONUtils.encodeToJSON(mapPayload));
    if (USE_HTTP_POST) {
      sURL = sURL_RPC;

      sPostData = URL_POST_PLATFORM_DATA + "&payload=" + sJSONPayload;
      sPostData = cn.appendURLSuffix(sPostData, true, sendAZID);

      if (DEBUG_URL) {
        debug("POST for " + mapProcessing.size() + ": " + sURL + "\n   DATA: " + sPostData);
      } else {
        debug("POST for " + mapProcessing.size() + ": " + sURL);
      }
    } else {
      sURL = sURL_RPC + URL_PLATFORM_MESSAGE + "&payload=" + sJSONPayload;

      sURL = cn.appendURLSuffix(sURL, false, sendAZID);

      if (DEBUG_URL) {
        debug("GET: " + sURL);
      } else {
        debug("GET: " + sURL_RPC + URL_PLATFORM_MESSAGE);
      }
    }

    final String fURL = sURL;
    final String fPostData = sPostData;

    // one at a time to take advantage of keep-alive connections

    dispatcher.dispatch(
        new AERunnable() {
          public void runSupport() {
            try {
              processQueueAsync(fURL, fPostData, mapProcessing);
            } catch (Throwable e) {
              if (e instanceof ResourceDownloaderException) {
                debug("Error while sending message(s) to Platform: " + e.toString());
              } else {
                debug("Error while sending message(s) to Platform", e);
              }
              for (Iterator iter = mapProcessing.keySet().iterator(); iter.hasNext(); ) {
                PlatformMessage message = (PlatformMessage) iter.next();
                PlatformMessengerListener l =
                    (PlatformMessengerListener) mapProcessing.get(message);
                if (l != null) {
                  try {
                    HashMap map = new HashMap();
                    map.put("text", e.toString());
                    map.put("Throwable", e);
                    l.replyReceived(message, REPLY_EXCEPTION, map);
                  } catch (Throwable e2) {
                    debug("Error while sending replyReceived", e2);
                  }
                }
              }
            }
          }
        });
  }
  public static void login(long contentNetworkID, long maxDelayMS) {
    PlatformManager pm = PlatformManagerFactory.getPlatformManager();
    String azComputerID = "";
    try {
      azComputerID = pm.getAzComputerID();
    } catch (PlatformManagerException e) {
    }

    String sourceRef = null;
    if (contentNetworkID != ConstantsVuze.DEFAULT_CONTENT_NETWORK_ID) {
      ContentNetwork cn =
          ContentNetworkManagerFactory.getSingleton().getContentNetwork(contentNetworkID);
      sourceRef = (String) cn.getPersistentProperty(ContentNetwork.PP_SOURCE_REF);
    }
    if (sourceRef == null) {
      sourceRef = "unknown";
    }

    Object[] params =
        new Object[] {
          "version",
          org.gudy.azureus2.core3.util.Constants.AZUREUS_VERSION,
          "locale",
          Locale.getDefault().toString(),
          "azCID",
          azComputerID,
          "vid",
          COConfigurationManager.getStringParameter("ID"),
          "source-ref",
          sourceRef
        };
    PlatformMessage message =
        new PlatformMessage("AZMSG", LISTENER_ID, "login", params, maxDelayMS);
    message.setContentNetworkID(contentNetworkID);

    PlatformMessengerListener listener =
        new PlatformMessengerListener() {

          public void replyReceived(PlatformMessage message, String replyType, Map reply) {
            if (reply == null) {
              return;
            }

            boolean allowMulti =
                MapUtils.getMapBoolean(reply, "allow-multi-rpc", PlatformMessenger.getAllowMulti());
            PlatformMessenger.setAllowMulti(allowMulti);

            try {
              List listURLs =
                  (List) MapUtils.getMapObject(reply, "url-whitelist", null, List.class);
              if (listURLs != null) {
                for (int i = 0; i < listURLs.size(); i++) {
                  String string = (String) listURLs.get(i);
                  UrlFilter.getInstance().addUrlWhitelist(string);
                }
              }
            } catch (Exception e) {
              Debug.out(e);
            }

            try {
              List listURLs =
                  (List) MapUtils.getMapObject(reply, "url-blacklist", null, List.class);
              if (listURLs != null) {
                for (int i = 0; i < listURLs.size(); i++) {
                  String string = (String) listURLs.get(i);
                  UrlFilter.getInstance().addUrlBlacklist(string);
                }
              }
            } catch (Exception e) {
              Debug.out(e);
            }

            try {
              List listDomains =
                  (List) MapUtils.getMapObject(reply, "tracker-domains", null, List.class);
              if (listDomains != null) {
                for (int i = 0; i < listDomains.size(); i++) {
                  String s = (String) listDomains.get(i);
                  PlatformTorrentUtils.addPlatformHost(s);
                  PlatformMessenger.debug("v3.login: got tracker domain of " + s);
                }
              }
            } catch (Exception e) {
              Debug.out(e);
            }

            if (message.getContentNetworkID() != ConstantsVuze.getDefaultContentNetwork().getID()) {
              return;
            }

            try {
              sendStats = MapUtils.getMapBoolean(reply, "send-stats", false);
              doUrlQOS = MapUtils.getMapBoolean(reply, "do-url-qos", false);
              allowSendDeviceList = MapUtils.getMapBoolean(reply, "send-device-list", false);
            } catch (Exception e) {
            }

            try {
              iRPCVersion = MapUtils.getMapInt(reply, "rpc-version", 0);
              playAfterURL = (String) MapUtils.getMapString(reply, "play-after-url", null);
            } catch (Exception e) {
              Debug.out(e);
            }

            platformLoginComplete = true;
            Object[] listeners = platformLoginCompleteListeners.toArray();
            platformLoginCompleteListeners = Collections.EMPTY_LIST;
            for (int i = 0; i < listeners.length; i++) {
              try {
                PlatformLoginCompleteListener l = (PlatformLoginCompleteListener) listeners[i];
                l.platformLoginComplete();
              } catch (Exception e) {
                Debug.out(e);
              }
            }
          }

          public void messageSent(PlatformMessage message) {}
        };

    PlatformMessenger.pushMessageNow(message, listener);
  }