All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.solace.spring.cloud.stream.binder.provisioning.SolaceProvisioningUtil Maven / Gradle / Ivy

There is a newer version: 5.0.1
Show newest version
package com.solace.spring.cloud.stream.binder.provisioning;

import com.solace.spring.cloud.stream.binder.properties.SolaceCommonProperties;
import com.solace.spring.cloud.stream.binder.properties.SolaceConsumerProperties;
import com.solace.spring.cloud.stream.binder.properties.SolaceProducerProperties;
import com.solace.spring.cloud.stream.binder.util.EndpointType;
import com.solace.spring.cloud.stream.binder.util.QualityOfService;
import com.solacesystems.jcsmp.*;
import org.springframework.cloud.stream.binder.ExtendedConsumerProperties;
import org.springframework.cloud.stream.binder.ExtendedProducerProperties;
import org.springframework.cloud.stream.provisioning.ProvisioningException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionException;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.StringUtils;

import java.util.UUID;

public class SolaceProvisioningUtil {

    private SolaceProvisioningUtil() {
    }

    public static EndpointProperties getEndpointProperties(SolaceCommonProperties properties) {
        EndpointProperties endpointProperties = new EndpointProperties();
        endpointProperties.setAccessType(properties.getQueueAccessType());
        endpointProperties.setDiscardBehavior(properties.getQueueDiscardBehaviour());
        endpointProperties.setMaxMsgRedelivery(properties.getQueueMaxMsgRedelivery());
        endpointProperties.setMaxMsgSize(properties.getQueueMaxMsgSize());
        endpointProperties.setPermission(properties.getQueuePermission());
        endpointProperties.setQuota(properties.getQueueQuota());
        endpointProperties.setRespectsMsgTTL(properties.getQueueRespectsMsgTtl());
        return endpointProperties;
    }

    public static EndpointProperties getErrorQueueEndpointProperties(SolaceConsumerProperties properties) {
        EndpointProperties endpointProperties = new EndpointProperties();
        endpointProperties.setAccessType(properties.getErrorQueueAccessType());
        endpointProperties.setDiscardBehavior(properties.getErrorQueueDiscardBehaviour());
        endpointProperties.setMaxMsgRedelivery(properties.getErrorQueueMaxMsgRedelivery());
        endpointProperties.setMaxMsgSize(properties.getErrorQueueMaxMsgSize());
        endpointProperties.setPermission(properties.getErrorQueuePermission());
        endpointProperties.setQuota(properties.getErrorQueueQuota());
        endpointProperties.setRespectsMsgTTL(properties.getErrorQueueRespectsMsgTtl());
        return endpointProperties;
    }

    public static ProducerFlowProperties getProducerFlowProperties(JCSMPSession jcsmpSession) {
        ProducerFlowProperties producerFlowProperties = new ProducerFlowProperties();
        Integer pubAckWindowSize = (Integer) jcsmpSession.getProperty(JCSMPProperties.PUB_ACK_WINDOW_SIZE);
        if (pubAckWindowSize != null) {
            producerFlowProperties.setWindowSize(pubAckWindowSize);
        }
        String ackEventMode = (String) jcsmpSession.getProperty(JCSMPProperties.ACK_EVENT_MODE);
        if (ackEventMode != null) {
            producerFlowProperties.setAckEventMode(ackEventMode);
        }
        return producerFlowProperties;
    }

    public static ConsumerFlowProperties getConsumerFlowProperties(String destinationName, ExtendedConsumerProperties properties) {
        ConsumerFlowProperties consumerFlowProperties = new ConsumerFlowProperties();
        final String selector = properties.getExtension().getSelector();
        consumerFlowProperties.setSelector((selector == null || selector.isBlank()) ? null : selector);
        if (EndpointType.TOPIC_ENDPOINT.equals(properties.getExtension().getEndpointType())) {
            String subscription;
            if (properties.getExtension().isAddDestinationAsSubscriptionToQueue()) {
                subscription = destinationName;
                if (properties.getExtension().getQueueAdditionalSubscriptions().length > 0) {
                    throw new IllegalArgumentException("No additional queue subscriptions permitted for topic endpoints");
                }
            } else {
                if (properties.getExtension().getQueueAdditionalSubscriptions().length != 1)
                    throw new IllegalArgumentException("Exactly one subscription must be provided for topic endpoints");
                subscription = properties.getExtension().getQueueAdditionalSubscriptions()[0];
            }
            consumerFlowProperties.setNewSubscription(JCSMPFactory.onlyInstance().createTopic(subscription));
        }

        return consumerFlowProperties;
    }

    public static boolean isAnonEndpoint(String groupName, QualityOfService qualityOfService) {
        return !StringUtils.hasText(groupName) || isTopicSubscription(qualityOfService);
    }

    public static boolean isDurableEndpoint(String groupName, QualityOfService qualityOfService) {
        return !isAnonEndpoint(groupName, qualityOfService);
    }

    public static boolean isTopicSubscription(QualityOfService qualityOfService) {
        return qualityOfService == QualityOfService.AT_MOST_ONCE;
    }

    public static String getTopicName(String baseTopicName, SolaceCommonProperties properties) {
        return baseTopicName;
    }

    public static String getQueueName(String topicName, String groupName, ExtendedProducerProperties properties) {
        String queueNameExpression = properties.getExtension().getQueueNameExpressionsForRequiredGroups().getOrDefault(groupName, properties.getExtension().getQueueNameExpression());
        return resolveQueueNameExpression(queueNameExpression, new ExpressionContextRoot(groupName, topicName, properties));
    }

    public static QueueNames getQueueNames(String topicName, String groupName, ExtendedConsumerProperties consumerProperties, boolean isAnonymous) {
        final String physicalGroupName = isAnonymous ? UUID.randomUUID().toString() : groupName;
        ExpressionContextRoot root = new ExpressionContextRoot(physicalGroupName, topicName, isAnonymous, consumerProperties);

        String resolvedQueueName = resolveQueueNameExpression(consumerProperties.getExtension().getQueueNameExpression(), root);
        String resolvedErrorQueueName = resolveQueueNameExpression(consumerProperties.getExtension().getErrorQueueNameExpression(), root);

        return new QueueNames(resolvedQueueName, resolvedErrorQueueName, physicalGroupName);
    }

    private static String resolveQueueNameExpression(String expression, ExpressionContextRoot root) {
        try {
            EvaluationContext evaluationContext = new StandardEvaluationContext(root);
            ExpressionParser parser = new SpelExpressionParser();
            Expression queueNameExp = parser.parseExpression(expression);
            String resolvedQueueName = (String) queueNameExp.getValue(evaluationContext);
            validateQueueName(resolvedQueueName, expression);
            return resolvedQueueName != null ? resolvedQueueName.trim() : null;
        } catch (ExpressionException e) {
            throw new ProvisioningException(String.format("Failed to evaluate Spring expression: %s", expression), e);
        }
    }

    private static void validateQueueName(String name, String expression) {
        if (!StringUtils.hasText(name)) {
            throw new ProvisioningException(String.format("Invalid SpEL expression %s as it resolves to a String that does not contain actual text.", expression));
        }
    }

    public static class QueueNames {
        private final String consumerGroupQueueName;
        private final String errorQueueName;
        private final String physicalGroupName;

        private QueueNames(String consumerGroupQueueName, String errorQueueName, String physicalGroupName) {
            this.consumerGroupQueueName = consumerGroupQueueName;
            this.errorQueueName = errorQueueName;
            this.physicalGroupName = physicalGroupName;
        }

        public String getConsumerGroupQueueName() {
            return consumerGroupQueueName;
        }

        public String getErrorQueueName() {
            return errorQueueName;
        }

        public String getPhysicalGroupName() {
            return physicalGroupName;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy