@Override
  public int createApplication(
      ServiceProvider serviceProvider, String tenantDomain, String userName)
      throws IdentityApplicationManagementException {
    try {

      startTenantFlow(tenantDomain, userName);

      // invoking the listeners
      List<ApplicationMgtListener> listeners = ApplicationMgtListenerServiceComponent.getListners();

      for (ApplicationMgtListener listener : listeners) {
        listener.createApplication(serviceProvider);
      }

      // first we need to create a role with the application name.
      // only the users in this role will be able to edit/update the
      // application.
      ApplicationMgtUtil.createAppRole(serviceProvider.getApplicationName());
      ApplicationDAO appDAO = ApplicationMgtSystemConfig.getInstance().getApplicationDAO();
      ApplicationMgtUtil.storePermission(
          serviceProvider.getApplicationName(), serviceProvider.getPermissionAndRoleConfig());

      return appDAO.createApplication(serviceProvider, tenantDomain);
    } catch (Exception e) {
      try {
        ApplicationMgtUtil.deleteAppRole(serviceProvider.getApplicationName());
        ApplicationMgtUtil.deletePermissions(serviceProvider.getApplicationName());
      } catch (Exception ignored) {
        if (log.isDebugEnabled()) {
          log.debug("Ignored the exception occurred while trying to delete the role : ", e);
        }
      }
      String error =
          "Error occurred while creating the application : " + serviceProvider.getApplicationName();
      log.error(error, e);
      throw new IdentityApplicationManagementException(error, e);
    } finally {
      endTenantFlow();
    }
  }
  @Override
  public void deleteApplication(String applicationName, String tenantDomain, String userName)
      throws IdentityApplicationManagementException {
    try {

      startTenantFlow(tenantDomain, userName);

      // invoking the listeners
      List<ApplicationMgtListener> listeners = ApplicationMgtListenerServiceComponent.getListners();

      for (ApplicationMgtListener listener : listeners) {
        listener.deleteApplication(applicationName);
      }

      if (!ApplicationMgtUtil.isUserAuthorized(applicationName)) {
        log.warn(
            "Illegal Access! User "
                + CarbonContext.getThreadLocalCarbonContext().getUsername()
                + " does not have access to the application "
                + applicationName);
        throw new IdentityApplicationManagementException("User not authorized");
      }

      ApplicationDAO appDAO = ApplicationMgtSystemConfig.getInstance().getApplicationDAO();
      ServiceProvider serviceProvider = appDAO.getApplication(applicationName, tenantDomain);
      appDAO.deleteApplication(applicationName);

      ApplicationMgtUtil.deleteAppRole(applicationName);
      ApplicationMgtUtil.deletePermissions(applicationName);

      if (serviceProvider != null
          && serviceProvider.getInboundAuthenticationConfig() != null
          && serviceProvider
                  .getInboundAuthenticationConfig()
                  .getInboundAuthenticationRequestConfigs()
              != null) {

        InboundAuthenticationRequestConfig[] configs =
            serviceProvider
                .getInboundAuthenticationConfig()
                .getInboundAuthenticationRequestConfigs();

        for (InboundAuthenticationRequestConfig config : configs) {

          if (IdentityApplicationConstants.Authenticator.SAML2SSO.NAME.equalsIgnoreCase(
                  config.getInboundAuthType())
              && config.getInboundAuthKey() != null) {

            SAMLApplicationDAO samlDAO =
                ApplicationMgtSystemConfig.getInstance().getSAMLClientDAO();
            samlDAO.removeServiceProviderConfiguration(config.getInboundAuthKey());

          } else if (IdentityApplicationConstants.OAuth2.NAME.equalsIgnoreCase(
                  config.getInboundAuthType())
              && config.getInboundAuthKey() != null) {
            OAuthApplicationDAO oathDAO =
                ApplicationMgtSystemConfig.getInstance().getOAuthOIDCClientDAO();
            oathDAO.removeOAuthApplication(config.getInboundAuthKey());

          } else if ("kerberos".equalsIgnoreCase(config.getInboundAuthType())
              && config.getInboundAuthKey() != null) {

            DirectoryServerManager directoryServerManager = new DirectoryServerManager();
            directoryServerManager.removeServer(config.getInboundAuthKey());

          } else if (IdentityApplicationConstants.Authenticator.WSTrust.NAME.equalsIgnoreCase(
                  config.getInboundAuthType())
              && config.getInboundAuthKey() != null) {
            try {
              AxisService stsService = getAxisConfig().getService(ServerConstants.STS_NAME);
              Parameter origParam =
                  stsService.getParameter(SAMLTokenIssuerConfig.SAML_ISSUER_CONFIG.getLocalPart());

              if (origParam != null) {
                OMElement samlConfigElem =
                    origParam
                        .getParameterElement()
                        .getFirstChildWithName(SAMLTokenIssuerConfig.SAML_ISSUER_CONFIG);

                SAMLTokenIssuerConfig samlConfig = new SAMLTokenIssuerConfig(samlConfigElem);
                samlConfig.getTrustedServices().remove(config.getInboundAuthKey());
                setSTSParameter(samlConfig);
                removeTrustedService(
                    ServerConstants.STS_NAME, ServerConstants.STS_NAME, config.getInboundAuthKey());
              } else {
                throw new IdentityApplicationManagementException(
                    "missing parameter : "
                        + SAMLTokenIssuerConfig.SAML_ISSUER_CONFIG.getLocalPart());
              }
            } catch (Exception e) {
              String error = "Error while removing a trusted service";
              log.error(error, e);
              throw new IdentityApplicationManagementException(error, e);
            }
          }
        }
      }

    } catch (Exception e) {
      String error = "Error occurred while deleting the application";
      log.error(error, e);
      throw new IdentityApplicationManagementException(error, e);
    } finally {
      endTenantFlow();
    }
  }
  @Override
  public void updateApplication(
      ServiceProvider serviceProvider, String tenantDomain, String userName)
      throws IdentityApplicationManagementException {
    try {

      try {
        startTenantFlow(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);

        IdentityServiceProviderCacheKey cacheKey =
            new IdentityServiceProviderCacheKey(tenantDomain, serviceProvider.getApplicationName());

        IdentityServiceProviderCache.getInstance().clearCacheEntry(cacheKey);

      } finally {
        endTenantFlow();
        startTenantFlow(tenantDomain, userName);
      }

      // invoking the listeners
      List<ApplicationMgtListener> listeners = ApplicationMgtListenerServiceComponent.getListners();
      for (ApplicationMgtListener listener : listeners) {
        listener.updateApplication(serviceProvider);
      }

      // check whether use is authorized to update the application.
      if (!ApplicationConstants.LOCAL_SP.equals(serviceProvider.getApplicationName())
          && !ApplicationMgtUtil.isUserAuthorized(
              serviceProvider.getApplicationName(), serviceProvider.getApplicationID())) {
        log.warn(
            "Illegal Access! User "
                + CarbonContext.getThreadLocalCarbonContext().getUsername()
                + " does not have access to the application "
                + serviceProvider.getApplicationName());
        throw new IdentityApplicationManagementException("User not authorized");
      }

      ApplicationDAO appDAO = ApplicationMgtSystemConfig.getInstance().getApplicationDAO();
      String storedAppName = appDAO.getApplicationName(serviceProvider.getApplicationID());
      appDAO.updateApplication(serviceProvider);

      ApplicationPermission[] permissions =
          serviceProvider.getPermissionAndRoleConfig().getPermissions();
      String applicationNode =
          ApplicationMgtUtil.getApplicationPermissionPath()
              + RegistryConstants.PATH_SEPARATOR
              + storedAppName;
      org.wso2.carbon.registry.api.Registry tenantGovReg =
          CarbonContext.getThreadLocalCarbonContext().getRegistry(RegistryType.USER_GOVERNANCE);

      boolean exist = tenantGovReg.resourceExists(applicationNode);
      if (exist && !storedAppName.equals(serviceProvider.getApplicationName())) {
        ApplicationMgtUtil.renameAppPermissionPathNode(
            storedAppName, serviceProvider.getApplicationName());
      }

      if (ArrayUtils.isNotEmpty(permissions)) {
        ApplicationMgtUtil.updatePermissions(serviceProvider.getApplicationName(), permissions);
      }
    } catch (Exception e) {
      String error = "Error occurred while updating the application";
      log.error(error, e);
      throw new IdentityApplicationManagementException(error, e);
    } finally {
      endTenantFlow();
    }
  }