public void propfind(HttpPropfind.Mode mode)
      throws URISyntaxException, IOException, DavException, HttpException {
    @Cleanup CloseableHttpResponse response = null;

    // processMultiStatus() requires knowledge of the actual content location,
    // so we have to handle redirections manually and create a new request for the new location
    for (int i = context.getRequestConfig().getMaxRedirects(); i > 0; i--) {
      HttpPropfind propfind = new HttpPropfind(location, mode);
      response = httpClient.execute(propfind, context);

      if (response.getStatusLine().getStatusCode() / 100 == 3) {
        location = DavRedirectStrategy.getLocation(propfind, response, context);
        Log.i(TAG, "Redirection on PROPFIND; trying again at new content URL: " + location);
        // don't forget to throw away the unneeded response content
        HttpEntity entity = response.getEntity();
        if (entity != null) {
          @Cleanup InputStream content = entity.getContent();
        }
      } else break; // answer was NOT a redirection, continue
    }
    if (response == null) throw new DavNoContentException();

    checkResponse(response); // will also handle Content-Location
    processMultiStatus(response);
  }
  public void multiGet(DavMultiget.Type type, String[] names)
      throws URISyntaxException, IOException, DavException, HttpException {
    @Cleanup CloseableHttpResponse response = null;

    // processMultiStatus() requires knowledge of the actual content location,
    // so we have to handle redirections manually and create a new request for the new location
    for (int i = context.getRequestConfig().getMaxRedirects(); i > 0; i--) {
      // build multi-get XML request
      List<String> hrefs = new LinkedList<>();
      for (String name : names)
        // name may contain "%" which have to be encoded → use non-quoting URI constructor and
        // getRawPath()
        // name may also contain ":", so prepend "./" because even the non-quoting URI constructor
        // parses after constructing
        // DAVdroid ensures that collections always have a trailing slash, so "./" won't go down in
        // directory hierarchy
        hrefs.add(location.resolve(new URI(null, null, "./" + name, null)).getRawPath());
      DavMultiget multiget = DavMultiget.newRequest(type, hrefs.toArray(new String[hrefs.size()]));

      StringWriter writer = new StringWriter();
      try {
        Serializer serializer = new Persister();
        serializer.write(multiget, writer);
      } catch (Exception ex) {
        Log.e(TAG, "Couldn't create XML multi-get request", ex);
        throw new DavException("Couldn't create multi-get request");
      }

      // submit REPORT request
      HttpReport report = new HttpReport(location, writer.toString());
      response = httpClient.execute(report, context);

      if (response.getStatusLine().getStatusCode() / 100 == 3) {
        location = DavRedirectStrategy.getLocation(report, response, context);
        Log.i(TAG, "Redirection on REPORT multi-get; trying again at new content URL: " + location);

        // don't forget to throw away the unneeded response content
        HttpEntity entity = response.getEntity();
        if (entity != null) {
          @Cleanup InputStream content = entity.getContent();
        }
      } else break; // answer was NOT a redirection, continue
    }
    if (response == null) throw new DavNoContentException();

    checkResponse(response); // will also handle Content-Location
    processMultiStatus(response);
  }