/**
   * Updates the user account information. After sucessful operation, the federation status
   * corresponding to the user with the remote provider is set to inactive.
   *
   * @param ni <code>NameIdentifier</code> object corresponding to a user
   * @return boolean containing the status of the update operation
   */
  protected boolean updateAccountInformation(NameIdentifier ni) {
    try {
      FSUtils.debug.message("FSFedTerminationHandler::updateAccountInformation: start");
      String searchDomain = remoteEntityId;
      // get name identifier to remove it from federation info key
      String nameId = null;
      String nameQualifier = null;
      if (ni != null) {
        nameQualifier = ni.getNameQualifier();
        if (nameQualifier != null
            && (nameQualifier.length() != 0)
            && !nameQualifier.equals(remoteEntityId)) {
          searchDomain = nameQualifier;
        }
        nameId = ni.getName();
      }
      if (nameId == null && acctInfo != null) {
        FSUtils.debug.message("FSAccountManager: getnameId in accInfo");
        NameIdentifier temp = acctInfo.getLocalNameIdentifier();
        if (temp != null) {
          nameId = temp.getName();
          nameQualifier = temp.getNameQualifier();
        } else {
          temp = acctInfo.getRemoteNameIdentifier();
          if (temp != null) {
            nameId = temp.getName();
            nameQualifier = temp.getNameQualifier();
          }
        }
      }
      FSAccountFedInfoKey fedInfoKey = new FSAccountFedInfoKey(nameQualifier, nameId);
      managerInst.removeAccountFedInfo(userID, fedInfoKey, searchDomain);

      if (FSUtils.debug.messageEnabled()) {
        FSUtils.debug.message(
            "FSFedTerminationHandler:: "
                + "updateAccountInformation deactivate successfully completed");
      }
    } catch (FSAccountMgmtException e) {
      FSUtils.debug.error(
          "FSFedTerminationHandler::updateAccountInformation "
              + FSUtils.bundle.getString(IFSConstants.TERMINATION_LOCAL_FAILED));
      String[] data = {userID};
      LogUtil.error(Level.INFO, LogUtil.TERMINATION_FAILED, data, ssoToken);
      return false;
    }
    // Clean SessionMap off the partner to be done here.
    if (FSUtils.debug.messageEnabled()) {
      FSUtils.debug.message("Cleaning Session manager for user : "******"Cleaning Session manager for remote provider: " + remoteEntityId);
      FSUtils.debug.message("Cleaning Session manager for hosted provider: " + hostedEntityId);
    }
    FSLogoutUtil.cleanSessionMapPartnerList(userID, remoteEntityId, metaAlias, null);
    return true;
  }
 /**
  * Generates Federation termination request based onthe <code>FSAccountFedInfo</code> object that
  * represents the account federation for a user between 2 providers.
  *
  * @param acctInfo represents the current user account information
  * @return termination request message
  */
 private FSFederationTerminationNotification createFederationTerminationRequest(
     FSAccountFedInfo acctInfo) {
   FSUtils.debug.message("FSFedTerminationHandler::createFederationTerminationRequest:");
   FSFederationTerminationNotification reqName = new FSFederationTerminationNotification();
   if (reqName != null) {
     NameIdentifier nameIdentifier = acctInfo.getRemoteNameIdentifier();
     if (nameIdentifier == null) {
       nameIdentifier = acctInfo.getLocalNameIdentifier();
     }
     if (FSUtils.debug.messageEnabled()) {
       FSUtils.debug.message("SP Provider Id : " + hostedEntityId);
     }
     reqName.setProviderId(hostedEntityId);
     reqName.setNameIdentifier(nameIdentifier);
     // TODO: Any more member settings + signature
     return reqName;
   } else {
     FSUtils.debug.message("failed to create termination request");
     FSUtils.debug.error(
         "FSFedTerminationHandler::createFederationTerminationRequest "
             + FSUtils.bundle.getString(IFSConstants.TERMINATION_REQUEST_CREATION));
     return null;
   }
 }
  /**
   * Initiates federation termination at remote end. The termination requested is constructed and
   * based on the profile the request is sent over SOAP or as HTTP redirect. Profile is always based
   * on the SPs profile
   *
   * @param acctInfo represents the user account federation information
   * @return <code>true</code> if termination request is sent to remote provider successfully;
   *     <code>false</code> otherwise.
   */
  private boolean doFederationTermination(
      HttpServletRequest request, HttpServletResponse response, FSAccountFedInfo acctInfo) {
    FSUtils.debug.message("Entered FSFedTerminationHandler::doFederationTermination");
    try {
      if (FSUtils.debug.messageEnabled()) {
        FSUtils.debug.message(
            "FSFedTerminationHandler::doFederationTermination create" + " request start");
      }
      FSFederationTerminationNotification reqFedTermination =
          createFederationTerminationRequest(acctInfo);
      reqFedTermination.setMinorVersion(
          FSServiceUtils.getMinorVersion(remoteDescriptor.getProtocolSupportEnumeration()));
      if (reqFedTermination == null) {
        if (FSUtils.debug.messageEnabled()) {
          FSUtils.debug.message(
              "FSIDPFedTerminationHandler::Termination request could " + "not be formed");
        }
        // Always show success page since local termination succeeded
        FSServiceUtils.returnLocallyAfterOperation(
            response,
            termination_done_url,
            true,
            IFSConstants.TERMINATION_SUCCESS,
            IFSConstants.TERMINATION_FAILURE);
        return false;
      }
      if (FSUtils.debug.messageEnabled()) {
        FSUtils.debug.message(
            "FSIDPFedTerminationHandler::Termination request formed" + "successfully");
      }
      // Find out which profile to use
      boolean isSOAPProfile = true;
      if (acctInfo.isRoleIDP()) {
        List hostProfiles = hostedDescriptor.getFederationTerminationNotificationProtocolProfile();
        if (hostProfiles == null || hostProfiles.isEmpty()) {
          FSUtils.debug.error(
              "FSFedTerminationHandler::"
                  + "doFederationTermination no termination profile"
                  + " cannot process request");
          FSServiceUtils.returnLocallyAfterOperation(
              response,
              termination_done_url,
              true,
              IFSConstants.TERMINATION_SUCCESS,
              IFSConstants.TERMINATION_FAILURE);
          return false;
        }
        String profile = (String) hostProfiles.iterator().next();
        if (profile.equalsIgnoreCase(IFSConstants.TERMINATION_SP_SOAP_PROFILE)
            || profile.equalsIgnoreCase(IFSConstants.TERMINATION_IDP_SOAP_PROFILE)) {
          isSOAPProfile = true;
        } else if (profile.equalsIgnoreCase(IFSConstants.TERMINATION_SP_HTTP_PROFILE)
            || profile.equalsIgnoreCase(IFSConstants.TERMINATION_IDP_HTTP_PROFILE)) {
          isSOAPProfile = false;
        } else {
          FSUtils.debug.error(
              "FSFedTerminationHandler::"
                  + "doFederationTermination Invalid termination profile"
                  + " cannot process request");
          FSServiceUtils.returnLocallyAfterOperation(
              response,
              termination_done_url,
              true,
              IFSConstants.TERMINATION_SUCCESS,
              IFSConstants.TERMINATION_FAILURE);
          return false;
        }
      } else {
        List remoteProfiles =
            remoteDescriptor.getFederationTerminationNotificationProtocolProfile();
        if (remoteProfiles == null || remoteProfiles.isEmpty()) {
          FSUtils.debug.error(
              "FSFedTerminationHandler::"
                  + "doFederationTermination no termination profile"
                  + " cannot process request");
          FSServiceUtils.returnLocallyAfterOperation(
              response,
              termination_done_url,
              true,
              IFSConstants.TERMINATION_SUCCESS,
              IFSConstants.TERMINATION_FAILURE);
          return false;
        }

        String profile = (String) remoteProfiles.iterator().next();
        if (profile.equalsIgnoreCase(IFSConstants.TERMINATION_SP_SOAP_PROFILE)
            || profile.equalsIgnoreCase(IFSConstants.TERMINATION_IDP_SOAP_PROFILE)) {
          isSOAPProfile = true;
        } else if (profile.equalsIgnoreCase(IFSConstants.TERMINATION_SP_HTTP_PROFILE)
            || profile.equalsIgnoreCase(IFSConstants.TERMINATION_IDP_HTTP_PROFILE)) {
          isSOAPProfile = false;
        } else {
          FSUtils.debug.error(
              "FSFedTerminationHandler::"
                  + "doFederationTermination Invalid termination profile"
                  + " cannot process request");
          FSServiceUtils.returnLocallyAfterOperation(
              response,
              termination_done_url,
              true,
              IFSConstants.TERMINATION_SUCCESS,
              IFSConstants.TERMINATION_FAILURE);
          return false;
        }
      }
      if (isSOAPProfile) {
        FSSOAPService instSOAP = FSSOAPService.getInstance();
        if (instSOAP != null) {
          FSUtils.debug.message("Signing suceeded. To call bindTerminationRequest");
          // String id = reqFedTermination.getRequestID();
          reqFedTermination.setID(IFSConstants.TERMINATIONID);
          SOAPMessage msgTermination = instSOAP.bind(reqFedTermination.toXMLString(true, true));
          if (msgTermination != null) {
            try {
              if (FSServiceUtils.isSigningOn()) {
                int minorVersion = reqFedTermination.getMinorVersion();
                if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) {
                  msgTermination =
                      signTerminationRequest(
                          msgTermination, IFSConstants.ID, reqFedTermination.getID());
                } else if (minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
                  msgTermination =
                      signTerminationRequest(
                          msgTermination,
                          IFSConstants.REQUEST_ID,
                          reqFedTermination.getRequestID());
                } else {
                  FSUtils.debug.message("invalid minor version.");
                }
              }
              boolean sendStatus =
                  instSOAP.sendTerminationMessage(
                      msgTermination, remoteDescriptor.getSoapEndpoint());
              // Call SP Adapter for SP initiated SOAP profile
              if (hostedProviderRole != null
                  && hostedProviderRole.equalsIgnoreCase(IFSConstants.SP)) {
                FederationSPAdapter spAdapter =
                    FSServiceUtils.getSPAdapter(hostedEntityId, hostedConfig);
                if (spAdapter != null) {
                  try {
                    spAdapter.postTerminationNotificationSuccess(
                        hostedEntityId,
                        request,
                        response,
                        userID,
                        reqFedTermination,
                        IFSConstants.TERMINATION_SP_SOAP_PROFILE);
                  } catch (Exception e) {
                    // ignore adapter exception
                    FSUtils.debug.error("postTerm.SP/SOAP", e);
                  }
                }
              }

              // Always show success page since local termination
              // succeeded and that is what is important
              FSServiceUtils.returnLocallyAfterOperation(
                  response,
                  termination_done_url,
                  true,
                  IFSConstants.TERMINATION_SUCCESS,
                  IFSConstants.TERMINATION_FAILURE);
              return sendStatus;
            } catch (Exception e) {
              FSUtils.debug.error(
                  "FSFedTerminationHandler::"
                      + "doFederationTermination "
                      + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE));
              // Always show success page since local
              // termination succeeded
              FSServiceUtils.returnLocallyAfterOperation(
                  response,
                  termination_done_url,
                  true,
                  IFSConstants.TERMINATION_SUCCESS,
                  IFSConstants.TERMINATION_FAILURE);
              return false;
            }
          } else {
            if (FSUtils.debug.messageEnabled()) {
              FSUtils.debug.message(
                  "FSSPFedTerminationHandler::doFederation"
                      + "Termination failed. Error in forming Message");
            }
            FSUtils.debug.error(
                "FSSPFedTerminationHandler.doFederationTermination "
                    + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE));
            // Always show success page since local termination
            // succeeded
            FSServiceUtils.returnLocallyAfterOperation(
                response,
                termination_done_url,
                true,
                IFSConstants.TERMINATION_SUCCESS,
                IFSConstants.TERMINATION_FAILURE);
            return false;
          }
        }
        if (FSUtils.debug.messageEnabled()) {
          FSUtils.debug.message(
              "FSFedTerminationHandler::doFederationTermination "
                  + "failed. Cannot get Service Manager instance");
        }
        FSUtils.debug.error(
            "FSSPFedTerminationHandler::doFederationTermination "
                + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE));
        // Always show success page since local termination succeeded
        FSServiceUtils.returnLocallyAfterOperation(
            response,
            termination_done_url,
            true,
            IFSConstants.TERMINATION_SUCCESS,
            IFSConstants.TERMINATION_FAILURE);
        return false;
      } else {
        if (FSUtils.debug.messageEnabled()) {
          FSUtils.debug.message(
              "FSFedTerminationHandler::doFederationTermination " + "In Redirect profile");
        }
        String urlEncodedRequest = reqFedTermination.toURLEncodedQueryString();
        // Sign the request querystring
        if (FSServiceUtils.isSigningOn()) {
          String certAlias =
              IDFFMetaUtils.getFirstAttributeValueFromConfig(
                  hostedConfig, IFSConstants.SIGNING_CERT_ALIAS);
          if (certAlias == null || certAlias.length() == 0) {
            if (FSUtils.debug.messageEnabled()) {
              FSUtils.debug.message(
                  "FSBrowserArtifactConsumerHandler:: "
                      + "signSAMLRequest:"
                      + "couldn't obtain this site's cert alias.");
            }
            throw new SAMLResponderException(FSUtils.bundle.getString(IFSConstants.NO_CERT_ALIAS));
          }
          urlEncodedRequest =
              FSSignatureUtil.signAndReturnQueryString(urlEncodedRequest, certAlias);
        }
        StringBuffer redirectURL = new StringBuffer();
        if (FSUtils.debug.messageEnabled()) {
          FSUtils.debug.message("Request to be sent : " + urlEncodedRequest);
        }
        String retURL = remoteDescriptor.getFederationTerminationServiceURL();
        redirectURL.append(retURL);
        if (retURL.indexOf(IFSConstants.QUESTION_MARK) == -1) {
          redirectURL.append(IFSConstants.QUESTION_MARK);
        } else {
          redirectURL.append(IFSConstants.AMPERSAND);
        }
        redirectURL.append(urlEncodedRequest);
        if (FSUtils.debug.messageEnabled()) {
          FSUtils.debug.message(
              "FSFedTerminationHandler::Redirect URL is " + redirectURL.toString());
        }
        // Call SP Adaper for SP initiated HTTP profile
        // ideally this should be called from the
        // FSTerminationReturnServlet, but info not available there
        if (hostedProviderRole != null && hostedProviderRole.equalsIgnoreCase(IFSConstants.SP)) {
          FederationSPAdapter spAdapter = FSServiceUtils.getSPAdapter(hostedEntityId, hostedConfig);
          if (spAdapter != null) {
            try {
              spAdapter.postTerminationNotificationSuccess(
                  hostedEntityId,
                  request,
                  response,
                  userID,
                  reqFedTermination,
                  IFSConstants.TERMINATION_SP_HTTP_PROFILE);
            } catch (Exception e) {
              // ignore adapter exception
              FSUtils.debug.error("postTerm.SP/HTTP", e);
            }
          }
        }
        response.sendRedirect(redirectURL.toString());
        return true;
      }
    } catch (IOException e) {
      FSUtils.debug.error(
          "FSFedTerminationHandler"
              + FSUtils.bundle.getString(IFSConstants.FEDERATION_REDIRECT_FAILED));
    } catch (FSMsgException e) {
      FSUtils.debug.error(
          "FSFedTerminationHandler::doFederationTermination "
              + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE));
    } catch (SAMLResponderException e) {
      FSUtils.debug.error(
          "FSFedTerminationHandler::doFederationTermination "
              + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE));
    }
    // Always show success page since local termination succeeded
    FSServiceUtils.returnLocallyAfterOperation(
        response,
        termination_done_url,
        true,
        IFSConstants.TERMINATION_SUCCESS,
        IFSConstants.TERMINATION_FAILURE);
    return false;
  }