protected SortedMap<String, String> prepareRequestParams(
      String responseFormat,
      IFacebookMethod method,
      Collection<Pair<String, CharSequence>> paramPairs)
      throws FacebookException {
    SortedMap<String, String> params = new TreeMap<String, String>();

    for (Pair<String, CharSequence> p : paramPairs) {
      final String key = p.first;
      CharSequence oldVal = params.put(key, BasicClientHelper.toString(p.second));
      if (oldVal != null) {
        log.warn(
            String.format(
                "For parameter %s, overwrote old value %s with new value %s.",
                key, oldVal, p.second));
      }
    }

    if (permissionsApiKey != null) {
      params.put("call_as_apikey", permissionsApiKey);
    }

    params.put("v", IFacebookRestClient.TARGET_API_VERSION);
    params.put("call_id", Long.toString(System.currentTimeMillis()));
    params.put("method", method.methodName());
    if (responseFormat != null) {
      params.put("format", responseFormat);
    }

    params.put("api_key", apiKey);
    boolean includeSession = !method.requiresNoSession() && sessionKey != null;
    if (includeSession) {
      params.put("session_key", sessionKey);
    }

    params.remove("sig");
    if (sessionSecret) {
      params.put("ss", "1");
    }
    String signature = FacebookSignatureUtil.generateSignature(params, secret);
    params.put("sig", signature);

    return params;
  }
 protected Document parseCallResult(InputStream data, IFacebookMethod method)
     throws FacebookException, IOException {
   try {
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     factory.setNamespaceAware(namespaceAware);
     DocumentBuilder builder = factory.newDocumentBuilder();
     Document doc = builder.parse(data);
     doc.normalizeDocument();
     stripEmptyTextNodes(doc);
     printDom(doc, method.methodName() + "| ");
     NodeList errors = doc.getElementsByTagName(ERROR_TAG);
     if (errors.getLength() > 0) {
       int errorCode =
           Integer.parseInt(errors.item(0).getFirstChild().getFirstChild().getTextContent());
       String message = errors.item(0).getFirstChild().getNextSibling().getTextContent();
       throw new FacebookException(errorCode, message);
     }
     return doc;
   } catch (ParserConfigurationException ex) {
     throw new RuntimeException("Trouble configuring XML Parser", ex);
   } catch (SAXException ex) {
     throw new RuntimeException("Trouble parsing XML from facebook", ex);
   }
 }
  public String callMethod(
      String responseFormat,
      IFacebookMethod method,
      Collection<Pair<String, CharSequence>> paramPairs,
      String fileName,
      InputStream fileStream)
      throws FacebookException {
    SortedMap<String, String> params = prepareRequestParams(responseFormat, method, paramPairs);
    final boolean fileCall = fileName != null || fileStream != null;
    if (batchMode) {
      if (fileCall) {
        throw new FacebookException(
            ErrorCode.GEN_INVALID_PARAMETER,
            "File upload API calls cannot be batched:  " + method.methodName());
      }
      // if we are running in batch mode, don't actually execute the query now, just add it to the
      // list
      boolean addToBatch = true;
      // FIXME what the heck is going on here??
      if (method.methodName().equals(FacebookMethod.USERS_GET_LOGGED_IN_USER.methodName())) {
        Exception trace = new Exception();
        StackTraceElement[] traceElems = trace.getStackTrace();
        int index = 0;
        for (StackTraceElement elem : traceElems) {
          if (elem.getMethodName().indexOf("_") != -1) {
            StackTraceElement caller = traceElems[index + 1];
            final boolean calledFromSelf =
                caller.getClassName().equals(BasicClient.class.getName());
            final boolean calledFromAuth = caller.getMethodName().startsWith("auth_");
            if (calledFromSelf && !calledFromAuth) {
              addToBatch = false;
            }
            break;
          }
          index++;
        }
      }
      if (addToBatch) {
        queries.add(new BatchQuery(method, params));
        // should return null be here or below
        // return null;
      }
      return null;
    }

    try {
      // FIXME when to use https?
      // when called from desktop, some methods require https
      boolean doHttps =
          FacebookMethod.AUTH_GET_SESSION.equals(method)
              && "true".equals(params.get("generate_session_secret"));
      URL url = (doHttps) ? serverUrlHttps : serverUrl;
      if (fileCall) {
        if (log.isDebugEnabled()) {
          log.debug(method.methodName() + ": POST-FILE: " + url.toString() + ": " + params);
        }
        return communicationStrategy.postRequest(url, params, fileName, fileStream);
      } else {
        if (log.isDebugEnabled()) {
          log.debug(method.methodName() + ": POST: " + url.toString() + ": " + params);
        }
        return communicationStrategy.postRequest(url, params);
      }
    } catch (IOException ex) {
      throw BasicClientHelper.runtimeException(ex);
    }
  }