
com.sap.cds.feature.messaging.em.client.EnterpriseMessagingWebhookManagementClient Maven / Gradle / Ivy
/**************************************************************************
* (C) 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
**************************************************************************/
package com.sap.cds.feature.messaging.em.client;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.sap.cds.feature.messaging.em.client.EnterpriseMessagingOAuth2PropertySupplier.EnterpriseMessagingOptions;
import com.sap.cds.integration.cloudsdk.rest.client.JsonRestClient;
import com.sap.cds.integration.cloudsdk.rest.client.JsonRestClientResponseException;
import com.sap.cds.services.environment.CdsProperties.ConnectionPool;
import com.sap.cloud.environment.servicebinding.api.ServiceBinding;
import com.sap.cloud.sdk.cloudplatform.connectivity.OnBehalfOf;
import com.sap.cloud.sdk.cloudplatform.connectivity.ServiceBindingDestinationOptions;
/**
* This class provides the REST client implementation providing the access to the SaaS
* and webhook management of enterprise messaging.
*/
public class EnterpriseMessagingWebhookManagementClient extends JsonRestClient {
private static final Logger logger = LoggerFactory.getLogger(EnterpriseMessagingWebhookManagementClient.class);
private static final String WEBHOOKS = "/messagingrest/v1/subscriptions";
private static final String TOPICS = "/messagingrest/v1/topics/{topic}/messages";
private static final String OAUTH_PATH = "/oauth/token";
static {
EnterpriseMessagingOAuth2PropertySupplier.initialize();
}
private final String name;
private final Map uaaCredentials;
@SuppressWarnings("unchecked")
public EnterpriseMessagingWebhookManagementClient(ServiceBinding binding, ConnectionPool connectionPoolConfig) {
super(ServiceBindingDestinationOptions.forService(binding)
.onBehalfOf(OnBehalfOf.TECHNICAL_USER_CURRENT_TENANT)
.withOption(EnterpriseMessagingOptions.WEBHOOK_MANAGEMENT_API)
.build(), connectionPoolConfig);
this.name = binding.getName().get(); // NOSONAR
this.uaaCredentials = (Map) binding.getCredentials().get("uaa");
}
/**
* Sends the specified string message to the specified topic.
*
* @param topic topic the message should be sent to
* @param message message to be sent
* @throws IOException throws when any connection problems occur
*/
public void sendMessage(String topic, String message) throws IOException {
logger.debug("Sending message from client '{}' to topic '{}'", name, topic);
Map headers = new HashMap<>();
headers.put("Content-Type", "text/plain");
headers.put("x-qos", "0");
postRequest(TOPICS.replace("{topic}", URLEncoder.encode(topic, StandardCharsets.UTF_8.toString())), message, headers);
}
/**
* Retrieves all registered webhooks.
*
* @return all registered webhooks
*
* @throws IOException throws when any connection problems occur
*/
public ArrayNode getRegisteredWebhooks() throws IOException {
logger.debug("Retrieving all registered webhooks of service binding '{}'", name);
return (ArrayNode) getRequest(WEBHOOKS);
}
/**
* Deletes the specified webhook.
*
* @param webhookName the name of the webhook to be deleted.
* @return true
if deleted and false
otherwise
*
* @throws IOException throws when any connection problems occur
*/
public boolean deleteWebhookRegistration(String webhookName) throws IOException {
logger.info("Deleting webhook for service '{}' of service binding '{}'", webhookName, name);
try {
deleteRequest(WEBHOOKS + "/" + webhookName);
} catch (JsonRestClientResponseException e) {
if (e.getResponseCode() == HttpStatus.SC_NOT_FOUND) {
// the registration is not available
return false;
}
throw e;
}
return true;
}
/**
* Creates or updates a new webhook registration.
*
* @param webhookName webhook name
* @param queue full qualified queue name
* @param hookUrl callback url
* @param tenantSubdomain the subdomain of the tenant, used to enrich the token endpoint URL
*
* @throws IOException throws when any connection problems occur
*/
public void createOrUpdateWebhookRegistration(String webhookName, String queue, String hookUrl, String tenantSubdomain) throws IOException {
// the webhook API does not support the PUT request. As workaround we delete the hook and finally create a new one.
deleteWebhookRegistration(webhookName);
logger.info("Creating webhook for service '{}' at URL '{}' for queue '{}' on service binding '{}'", webhookName, hookUrl, queue, name);
ObjectNode data = mapper.createObjectNode();
data.put("name", webhookName);
data.put("address", "queue:" + queue);
data.put("qos", 1);
ObjectNode pushConfig = mapper.createObjectNode();
data.set("pushConfig", pushConfig);
pushConfig.put("type", "webhook");
pushConfig.put("endpoint", hookUrl);
pushConfig.put("exemptHandshake", true);
addSecuritySchema(pushConfig, tenantSubdomain);
postRequest(WEBHOOKS, data);
}
private String replaceSubdomain(String url, String subdomain) {
if (subdomain != null) {
url = url.replaceFirst("://[^\\.]*\\.", "://" + subdomain + '.');
}
return url;
}
private void addSecuritySchema(ObjectNode config, String tenantSubdomain) {
ObjectNode securitySchema = mapper.createObjectNode();
config.set("securitySchema", securitySchema);
securitySchema.put("grantType", "client_credentials");
securitySchema.put("clientId", (String) uaaCredentials.get("clientid"));
// check type
if ("x509".equals(uaaCredentials.get("credential-type"))) {
securitySchema.put("tokenUrl", replaceSubdomain((String) uaaCredentials.get("certurl"), tenantSubdomain) + OAUTH_PATH);
securitySchema.put("type", "oauth2-x509");
securitySchema.put("certificate", (String) uaaCredentials.get("certificate"));
securitySchema.put("key", (String) uaaCredentials.get("key"));
} else {
securitySchema.put("tokenUrl", replaceSubdomain((String) uaaCredentials.get("url"), tenantSubdomain) + OAUTH_PATH);
securitySchema.put("type", "oauth2");
securitySchema.put("clientSecret", (String) uaaCredentials.get("clientsecret"));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy