code: private HTTPAnnounceRequestMessage parseQuery(final String uri, final String hostAddress)
            throws IOException, MessageValidationException {
      Map<String, BEValue> params = new HashMap<String, BEValue>();
  
      try {
  //			String uri = request.getAddress().toString();
        for (String pair : uri.split("[?]")[1].split("&")) {
          String[] keyval = pair.split("[=]", 2);
          if (keyval.length == 1) {
            this.recordParam(params, keyval[0], null);
          } else {
            this.recordParam(params, keyval[0], keyval[1]);
          }
        }
      } catch (ArrayIndexOutOfBoundsException e) {
        params.clear();
      }
  
      // Make sure we have the peer IP, fallbacking on the request's source
      // address if the peer didn't provide it.
      if (params.get("ip") == null) {
        params.put("ip", new BEValue(
                hostAddress,
                Constants.BYTE_ENCODING));
      }
  
      return HTTPAnnounceRequestMessage.parse(new BEValue(params));
    }
docs: Parse the query parameters using our defined BYTE_ENCODING.
  <p>
  <p>
  Because we're expecting byte-encoded strings as query parameters, we
  can't rely on SimpleHTTP's QueryParser which uses the wrong encoding for
  the job and returns us unparsable byte data. We thus have to implement
  our own little parsing method that uses BYTE_ENCODING to decode
  parameters from the URI.
  </p>
  <p>
  <p>
  <b>Note:</b> array parameters are not supported. If a key is present
  multiple times in the URI, the latest value prevails. We don't really
  need to implement this functionality as this never happens in the
  Tracker HTTP protocol.
  </p>
  
  @param uri
  @param hostAddress
  @return The {@link AnnounceRequestMessage} representing the client's
  announce request.