/**
   * Call the GetMethod.
   *
   * @param url The URL for the HTTP GET method.
   * @return GetMethod
   * @throws WebserverSystemException If connection failed.
   */
  public GetMethod get(final String url, final HashMap<String, String> params)
      throws RepositoryException {

    GetMethod get = null;
    try {
      get = new GetMethod(url);
      Set<String> paramKeys = params.keySet();
      NameValuePair[] paramsArray = new NameValuePair[paramKeys.size()];

      Iterator<String> iterator = paramKeys.iterator();
      int i = 0;
      while (iterator.hasNext()) {
        String key = iterator.next();
        String value = params.get(key);
        paramsArray[i] = new NameValuePair(key, value);
        i++;
      }
      if (params.size() > 0) {
        String queryString = EncodingUtil.formUrlEncode(paramsArray, "UTF-8");
        get.setQueryString(queryString);
      }
      // get.setQueryString(paramsArray);
      int responseCode = getHttpClient().executeMethod(get);
      if ((responseCode / 100) != (HTTP_RESPONSE_OK / 100)) {

        String message = get.getResponseBodyAsString();
        if (message == null) {
          Header header = get.getResponseHeader("eSciDocException");
          String value = header.getValue();
          if (value != null) {
            message = "GET-Request with url " + url + " results with Exception:" + value + " .";
          } else {
            message = "Connection to '" + url + "' failed with response code " + responseCode;
          }
        }

        get.releaseConnection();
        log.info(message);
        throw new RepositoryException(message);
      }
    } catch (HttpException e) {
      throw new RepositoryException(e.getMessage(), e);
    } catch (IOException e) {
      throw new RepositoryException(e.getMessage(), e);
    }

    return get;
  }
  /** Guts of the implementation, returns a complete Choices result, or null for a failure. */
  private Choices queryPerson(String text, int start, int limit) {
    // punt if there is no query text
    if (text == null || text.trim().length() == 0) return new Choices(true);

    // 1. build CQL query
    DCPersonName pn = new DCPersonName(text);
    StringBuilder query = new StringBuilder();
    query
        .append("local.FirstName = \"")
        .append(pn.getFirstNames())
        .append("\" and local.FamilyName = \"")
        .append(pn.getLastName())
        .append("\"");

    // XXX arbitrary default limit - should be configurable?
    if (limit == 0) limit = 50;

    NameValuePair args[] = new NameValuePair[6];
    args[0] = new NameValuePair("operation", "searchRetrieve");
    args[1] = new NameValuePair("version", "1.1");
    args[2] = new NameValuePair("recordSchema", "info:srw/schema/1/marcxml-v1.1");
    args[3] = new NameValuePair("query", query.toString());
    args[4] = new NameValuePair("maximumRecords", String.valueOf(limit));
    args[5] = new NameValuePair("startRecord", String.valueOf(start + 1));
    HttpClient hc = new HttpClient();
    String srUrl = url + "?" + EncodingUtil.formUrlEncode(args, "UTF8");
    GetMethod get = new GetMethod(srUrl);

    log.debug("Trying SRU query, URL=" + srUrl);

    // 2. web request
    try {
      int status = hc.executeMethod(get);
      if (status == 200) {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
        XMLReader xr = sp.getXMLReader();
        SRUHandler handler = new SRUHandler();

        // XXX FIXME: should turn off validation here explicitly, but
        //  it seems to be off by default.
        xr.setFeature("http://xml.org/sax/features/namespaces", true);
        xr.setContentHandler(handler);
        xr.setErrorHandler(handler);
        xr.parse(new InputSource(get.getResponseBodyAsStream()));

        // this probably just means more results available..
        if (handler.hits != handler.result.size())
          log.warn(
              "Discrepency in results, result.length="
                  + handler.result.size()
                  + ", yet expected results="
                  + handler.hits);
        boolean more = handler.hits > (start + handler.result.size());

        // XXX add non-auth option; perhaps the UI should do this?
        // XXX it's really a policy matter if they allow unauth result.
        // XXX good, stop it.
        // handler.result.add(new Choice("", text, "Non-Authority: \""+text+"\""));

        int confidence;
        if (handler.hits == 0) confidence = Choices.CF_NOTFOUND;
        else if (handler.hits == 1) confidence = Choices.CF_UNCERTAIN;
        else confidence = Choices.CF_AMBIGUOUS;
        return new Choices(
            handler.result.toArray(new Choice[handler.result.size()]),
            start,
            handler.hits,
            confidence,
            more);
      }
    } catch (HttpException e) {
      log.error("SRU query failed: ", e);
      return new Choices(true);
    } catch (IOException e) {
      log.error("SRU query failed: ", e);
      return new Choices(true);
    } catch (ParserConfigurationException e) {
      log.warn("Failed parsing SRU result: ", e);
      return new Choices(true);
    } catch (SAXException e) {
      log.warn("Failed parsing SRU result: ", e);
      return new Choices(true);
    } finally {
      get.releaseConnection();
    }
    return new Choices(true);
  }