docs: public static String normalizeParameters(String requestUrl,
        Map<String, String> protocolParameters) throws AuthException {
      SortedSet<RequestParameter> parameters = new TreeSet<>();
      int index = requestUrl.indexOf('?');
      if (index > 0) {
        String query = requestUrl.substring(index + 1);
        Iterator<String> i = new StringIterator(query, "&");
        while (i.hasNext()) {
          String parameter = i.next();
          int equalsIndex = parameter.indexOf('=');
          if (equalsIndex > 0) {
            parameters.add(new RequestParameter(AuthUtils.percentDecode(parameter.substring(0, equalsIndex))
                , AuthUtils.percentDecode(parameter.substring(equalsIndex + 1))));
          } else if (equalsIndex == -1) {
            parameters.add(new RequestParameter(AuthUtils.percentDecode(parameter)));
          }
        }
      }
  
      for (Entry<String, String> entry : protocolParameters.entrySet()) {
        parameters.add(new RequestParameter(entry.getKey(), entry.getValue()));
      }
  
      StringBuilder normalized = new StringBuilder();
      Iterator<RequestParameter> parameterIterator = parameters.iterator();
      if (parameterIterator.hasNext()) {
        RequestParameter requestParameter = parameterIterator.next();
        normalized.append(requestParameter.getEncodedName())
            .append('=').append(requestParameter.getEncodedValue());
        while (parameterIterator.hasNext()) {
          requestParameter = parameterIterator.next();
          normalized.append('&').append(requestParameter.getEncodedName())
              .append('=').append(requestParameter.getEncodedValue());
        }
      }
  
      return normalized.toString();
    }