/**
   * Revoke tokens issued to OAuth clients
   *
   * @param revokeRequestDTO DTO representing consumerKey, consumerSecret and tokens[]
   * @return revokeRespDTO DTO representing success or failure message
   */
  public OAuthRevocationResponseDTO revokeTokenByOAuthClient(
      OAuthRevocationRequestDTO revokeRequestDTO) {

    // fix here remove associated cache entry
    TokenMgtDAO tokenMgtDAO = new TokenMgtDAO();
    OAuthRevocationResponseDTO revokeResponseDTO = new OAuthRevocationResponseDTO();

    try {
      if (StringUtils.isNotEmpty(revokeRequestDTO.getConsumerKey())
          && StringUtils.isNotEmpty(revokeRequestDTO.getToken())) {

        boolean refreshTokenFirst = false;
        if (StringUtils.equals(
            GrantType.REFRESH_TOKEN.toString(), revokeRequestDTO.getToken_type())) {
          refreshTokenFirst = true;
        }

        RefreshTokenValidationDataDO refreshTokenDO = null;
        AccessTokenDO accessTokenDO = null;

        if (refreshTokenFirst) {

          refreshTokenDO =
              tokenMgtDAO.validateRefreshToken(
                  revokeRequestDTO.getConsumerKey(), revokeRequestDTO.getToken());

          if (refreshTokenDO == null
              || StringUtils.isEmpty(refreshTokenDO.getRefreshTokenState())
              || !(OAuthConstants.TokenStates.TOKEN_STATE_ACTIVE.equals(
                      refreshTokenDO.getRefreshTokenState())
                  || OAuthConstants.TokenStates.TOKEN_STATE_EXPIRED.equals(
                      refreshTokenDO.getRefreshTokenState()))) {

            accessTokenDO = tokenMgtDAO.retrieveAccessToken(revokeRequestDTO.getToken(), true);
            refreshTokenDO = null;
          }

        } else {
          accessTokenDO = tokenMgtDAO.retrieveAccessToken(revokeRequestDTO.getToken(), true);
          if (accessTokenDO == null) {

            refreshTokenDO =
                tokenMgtDAO.validateRefreshToken(
                    revokeRequestDTO.getConsumerKey(), revokeRequestDTO.getToken());

            if (refreshTokenDO == null
                || StringUtils.isEmpty(refreshTokenDO.getRefreshTokenState())
                || !(OAuthConstants.TokenStates.TOKEN_STATE_ACTIVE.equals(
                        refreshTokenDO.getRefreshTokenState())
                    || OAuthConstants.TokenStates.TOKEN_STATE_EXPIRED.equals(
                        refreshTokenDO.getRefreshTokenState()))) {
              return revokeResponseDTO;
            }
          }
        }

        String grantType = StringUtils.EMPTY;

        if (accessTokenDO != null) {
          grantType = accessTokenDO.getGrantType();
        } else if (refreshTokenDO != null) {
          grantType = refreshTokenDO.getGrantType();
        }

        if (!StringUtils.equals(OAuthConstants.GrantTypes.IMPLICIT, grantType)
            && !OAuth2Util.authenticateClient(
                revokeRequestDTO.getConsumerKey(), revokeRequestDTO.getConsumerSecret())) {

          OAuthRevocationResponseDTO revokeRespDTO = new OAuthRevocationResponseDTO();
          revokeRespDTO.setError(true);
          revokeRespDTO.setErrorCode(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
          revokeRespDTO.setErrorMsg("Unauthorized Client");

          return revokeRespDTO;
        }

        if (refreshTokenDO != null) {

          org.wso2.carbon.identity.oauth.OAuthUtil.clearOAuthCache(
              revokeRequestDTO.getConsumerKey(),
              refreshTokenDO.getAuthorizedUser(),
              OAuth2Util.buildScopeString(refreshTokenDO.getScope()));

          org.wso2.carbon.identity.oauth.OAuthUtil.clearOAuthCache(
              revokeRequestDTO.getConsumerKey(), refreshTokenDO.getAuthorizedUser());

          org.wso2.carbon.identity.oauth.OAuthUtil.clearOAuthCache(refreshTokenDO.getAccessToken());
          tokenMgtDAO.revokeTokens(new String[] {refreshTokenDO.getAccessToken()});

          addRevokeResponseHeaders(
              revokeResponseDTO,
              refreshTokenDO.getAccessToken(),
              revokeRequestDTO.getToken(),
              refreshTokenDO.getAuthorizedUser().toString());

        } else if (accessTokenDO != null) {
          org.wso2.carbon.identity.oauth.OAuthUtil.clearOAuthCache(
              revokeRequestDTO.getConsumerKey(),
              accessTokenDO.getAuthzUser(),
              OAuth2Util.buildScopeString(accessTokenDO.getScope()));
          org.wso2.carbon.identity.oauth.OAuthUtil.clearOAuthCache(
              revokeRequestDTO.getConsumerKey(), accessTokenDO.getAuthzUser());
          org.wso2.carbon.identity.oauth.OAuthUtil.clearOAuthCache(revokeRequestDTO.getToken());
          tokenMgtDAO.revokeTokens(new String[] {revokeRequestDTO.getToken()});
          addRevokeResponseHeaders(
              revokeResponseDTO,
              revokeRequestDTO.getToken(),
              accessTokenDO.getRefreshToken(),
              accessTokenDO.getAuthzUser().toString());
        }

        return revokeResponseDTO;

      } else {
        revokeResponseDTO.setError(true);
        revokeResponseDTO.setErrorCode(OAuth2ErrorCodes.INVALID_REQUEST);
        revokeResponseDTO.setErrorMsg("Invalid revocation request");
        return revokeResponseDTO;
      }

    } catch (InvalidOAuthClientException e) {
      log.error("Unauthorized Client", e);
      OAuthRevocationResponseDTO revokeRespDTO = new OAuthRevocationResponseDTO();
      revokeRespDTO.setError(true);
      revokeRespDTO.setErrorCode(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
      revokeRespDTO.setErrorMsg("Unauthorized Client");
      return revokeRespDTO;
    } catch (IdentityException e) {
      log.error("Error occurred while revoking authorization grant for applications", e);
      OAuthRevocationResponseDTO revokeRespDTO = new OAuthRevocationResponseDTO();
      revokeRespDTO.setError(true);
      revokeRespDTO.setErrorCode(OAuth2ErrorCodes.SERVER_ERROR);
      revokeRespDTO.setErrorMsg(
          "Error occurred while revoking authorization grant for applications");
      return revokeRespDTO;
    }
  }
  @Override
  public boolean validateScope(AccessTokenDO accessTokenDO, String resource)
      throws IdentityOAuth2Exception {
    boolean status = true;
    // Extract the url & http method
    int idx = resource.lastIndexOf(':');
    String url = resource.substring(0, idx);
    String method = resource.substring(++idx, resource.length());
    // This is to remove the url params for request path.
    int urlParamIndex = url.indexOf('?');
    if (urlParamIndex > 0) {
      url = url.substring(0, urlParamIndex);
    }

    Properties properties = new Properties();
    properties.put(PermissionBasedScopeValidator.URL_PROPERTY, url.toLowerCase());
    properties.put(PermissionBasedScopeValidator.HTTP_METHOD_PROPERTY, method.toUpperCase());
    PermissionManagerService permissionManagerService =
        OAuthExtensionsDataHolder.getInstance().getPermissionManagerService();
    try {
      Permission permission = permissionManagerService.getPermission(properties);
      User authzUser = accessTokenDO.getAuthzUser();
      if ((permission != null) && (authzUser != null)) {
        if (permission.getPath() == null) {
          if (log.isDebugEnabled()) {
            log.debug("Permission is not defined for the resource '" + resource + "'");
          }
          return true;
        }
        String username = authzUser.getUserName();
        String userStore = authzUser.getUserStoreDomain();
        int tenantId = OAuthExtUtils.getTenantId(authzUser.getTenantDomain());
        UserRealm userRealm =
            OAuthExtensionsDataHolder.getInstance().getRealmService().getTenantUserRealm(tenantId);
        if (userRealm != null && userRealm.getAuthorizationManager() != null) {
          if (userStore != null) {
            status =
                userRealm
                    .getAuthorizationManager()
                    .isUserAuthorized(
                        userStore + "/" + username,
                        permission.getPath(),
                        PermissionMethod.UI_EXECUTE);
          } else {
            status =
                userRealm
                    .getAuthorizationManager()
                    .isUserAuthorized(username, permission.getPath(), PermissionMethod.UI_EXECUTE);
          }
        }
      }
    } catch (PermissionManagementException e) {
      log.error(
          "Error occurred while validating the resource scope for : "
              + resource
              + ", Msg = "
              + e.getMessage(),
          e);
    } catch (UserStoreException e) {
      log.error("Error occurred while retrieving user store. " + e.getMessage());
    }
    return status;
  }