/*
   * Repeatedly access the protected resource after the client has
   * successfully logged-in to the webapp. The current session attributes
   * will be used and cannot be changed.
   *  3. after successful login, follow the redirect to the original page
   *  4. repeatedly access the protected resource to demonstrate
   *     persistence of the authenticated session
   *
   * @param resourceMethod HTTP method for accessing the protected resource
   * @param protectedUri to access (with or withour sessionid)
   * @param useContinue whether the HTTP client should expect a 100 Continue
   * @param clientShouldUseCookies whether the client should send cookies
   * @param serverWillUseCookies whether the server should send cookies
   *
   */
  private void doTestProtected(
      String resourceMethod, String protectedUri, boolean useContinue, int phase, int repeatCount)
      throws Exception {

    // Subsequent requests - keep accessing the protected resource
    for (int i = 0; i < repeatCount; i++) {
      client.setUseContinue(useContinue);
      client.doResourceRequest(resourceMethod, false, protectedUri, null);
      assertTrue(client.isResponse200());
      assertTrue(client.isResponseBodyOK(phase));
      client.reset();
    }
  }
  /*
   * Choreograph the steps of the test dialogue with the server
   *  1. while not authenticated, try to access a protected resource
   *  2. respond to the login challenge with good credentials
   *  3. after successful login, follow the redirect to the original page
   *  4. repeatedly access the protected resource to demonstrate
   *     persistence of the authenticated session
   *
   * @param resourceMethod HTTP method for accessing the protected resource
   * @param redirectMethod HTTP method for the login FORM reply
   * @param useContinue whether the HTTP client should expect a 100 Continue
   * @param clientShouldUseCookies whether the client should send cookies
   * @param serverWillUseCookies whether the server should send cookies
   *
   */
  private String doTest(
      String resourceMethod,
      String redirectMethod,
      boolean useContinue,
      boolean clientShouldUseCookies,
      boolean serverWillUseCookies,
      boolean serverWillChangeSessid)
      throws Exception {

    client =
        new FormAuthClient(clientShouldUseCookies, serverWillUseCookies, serverWillChangeSessid);

    // First request for protected resource gets the login page
    client.setUseContinue(useContinue);
    client.doResourceRequest(resourceMethod, false, null, null);
    assertTrue(client.isResponse200());
    assertTrue(client.isResponseBodyOK());
    String loginUri =
        client.extractBodyUri(FormAuthClient.LOGIN_PARAM_TAG, FormAuthClient.LOGIN_RESOURCE);
    String originalSessionId = null;
    if (serverWillUseCookies && clientShouldUseCookies) {
      originalSessionId = client.getSessionId();
    } else {
      originalSessionId = client.extractPathSessionId(loginUri);
    }
    client.reset();

    // Second request replies to the login challenge
    client.setUseContinue(useContinue);
    client.doLoginRequest(loginUri);
    assertTrue("login failed " + client.getResponseLine(), client.isResponse302());
    assertTrue(client.isResponseBodyOK());
    String redirectUri = client.getRedirectUri();
    client.reset();

    // Third request - the login was successful so
    // follow the redirect to the protected resource
    client.doResourceRequest(redirectMethod, true, redirectUri, null);
    if ("POST".equals(redirectMethod)) {
      client.setUseContinue(useContinue);
    }
    assertTrue(client.isResponse200());
    assertTrue(client.isResponseBodyOK());
    String protectedUri =
        client.extractBodyUri(FormAuthClient.RESOURCE_PARAM_TAG, FormAuthClient.PROTECTED_RESOURCE);
    String newSessionId = null;
    if (serverWillUseCookies && clientShouldUseCookies) {
      newSessionId = client.getSessionId();
    } else {
      newSessionId = client.extractPathSessionId(protectedUri);
    }
    boolean sessionIdIsChanged = !(originalSessionId.equals(newSessionId));
    assertTrue(sessionIdIsChanged == serverWillChangeSessid);
    client.reset();

    // Subsequent requests - keep accessing the protected resource
    doTestProtected(resourceMethod, protectedUri, useContinue, FormAuthClient.LOGIN_SUCCESSFUL, 5);

    return protectedUri; // in case more requests will be issued
  }