org.springframework.cloud.stream.binding.BindingService.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.cloud.stream.binding.BindingService.java

Source

/*
 * Copyright 2015-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.cloud.stream.binding;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeanUtils;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.cloud.stream.binder.Binder;
import org.springframework.cloud.stream.binder.BinderFactory;
import org.springframework.cloud.stream.binder.Binding;
import org.springframework.cloud.stream.binder.ConsumerProperties;
import org.springframework.cloud.stream.binder.ExtendedConsumerProperties;
import org.springframework.cloud.stream.binder.ExtendedProducerProperties;
import org.springframework.cloud.stream.binder.ExtendedPropertiesBinder;
import org.springframework.cloud.stream.binder.ProducerProperties;
import org.springframework.cloud.stream.config.BindingServiceProperties;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.beanvalidation.CustomValidatorBean;

/**
 * Handles binding of input/output targets by delegating to an underlying
 * {@link Binder}.
 *
 * @author Mark Fisher
 * @author Dave Syer
 * @author Marius Bogoevici
 * @author Ilayaperumal Gopinathan
 * @author Gary Russell
 */
public class BindingService {

    private final CustomValidatorBean validator;

    private final Log log = LogFactory.getLog(BindingService.class);

    private BinderFactory binderFactory;

    private final BindingServiceProperties bindingServiceProperties;

    private final Map<String, Binding<?>> producerBindings = new HashMap<>();

    private final Map<String, List<Binding<?>>> consumerBindings = new HashMap<>();

    public BindingService(BindingServiceProperties bindingServiceProperties, BinderFactory binderFactory) {
        this.bindingServiceProperties = bindingServiceProperties;
        this.binderFactory = binderFactory;
        this.validator = new CustomValidatorBean();
        this.validator.afterPropertiesSet();
    }

    @SuppressWarnings("unchecked")
    public <T> Collection<Binding<T>> bindConsumer(T input, String inputName) {
        String bindingTarget = this.bindingServiceProperties.getBindingDestination(inputName);
        String[] bindingTargets = StringUtils.commaDelimitedListToStringArray(bindingTarget);
        Collection<Binding<T>> bindings = new ArrayList<>();
        Binder<T, ConsumerProperties, ?> binder = (Binder<T, ConsumerProperties, ?>) getBinder(inputName,
                input.getClass());
        ConsumerProperties consumerProperties = this.bindingServiceProperties.getConsumerProperties(inputName);
        if (binder instanceof ExtendedPropertiesBinder) {
            Object extension = ((ExtendedPropertiesBinder) binder).getExtendedConsumerProperties(inputName);
            ExtendedConsumerProperties extendedConsumerProperties = new ExtendedConsumerProperties(extension);
            BeanUtils.copyProperties(consumerProperties, extendedConsumerProperties);
            consumerProperties = extendedConsumerProperties;
        }
        validate(consumerProperties);
        for (String target : bindingTargets) {
            Binding<T> binding = binder.bindConsumer(target, bindingServiceProperties.getGroup(inputName), input,
                    consumerProperties);
            bindings.add(binding);
        }
        bindings = Collections.unmodifiableCollection(bindings);
        this.consumerBindings.put(inputName, new ArrayList<Binding<?>>(bindings));
        return bindings;
    }

    @SuppressWarnings("unchecked")
    public <T> Binding<T> bindProducer(T output, String outputName) {
        String bindingTarget = this.bindingServiceProperties.getBindingDestination(outputName);
        Binder<T, ?, ProducerProperties> binder = (Binder<T, ?, ProducerProperties>) getBinder(outputName,
                output.getClass());
        ProducerProperties producerProperties = this.bindingServiceProperties.getProducerProperties(outputName);
        if (binder instanceof ExtendedPropertiesBinder) {
            Object extension = ((ExtendedPropertiesBinder) binder).getExtendedProducerProperties(outputName);
            ExtendedProducerProperties extendedProducerProperties = new ExtendedProducerProperties<>(extension);
            BeanUtils.copyProperties(producerProperties, extendedProducerProperties);
            producerProperties = extendedProducerProperties;
        }
        validate(producerProperties);
        Binding<T> binding = binder.bindProducer(bindingTarget, output, producerProperties);
        this.producerBindings.put(outputName, binding);
        return binding;
    }

    public void unbindConsumers(String inputName) {
        List<Binding<?>> bindings = this.consumerBindings.remove(inputName);
        if (bindings != null && !CollectionUtils.isEmpty(bindings)) {
            for (Binding<?> binding : bindings) {
                binding.unbind();
            }
        } else if (log.isWarnEnabled()) {
            log.warn("Trying to unbind '" + inputName + "', but no binding found.");
        }
    }

    public void unbindProducers(String outputName) {
        Binding<?> binding = this.producerBindings.remove(outputName);
        if (binding != null) {
            binding.unbind();
        } else if (log.isWarnEnabled()) {
            log.warn("Trying to unbind '" + outputName + "', but no binding found.");
        }
    }

    @SuppressWarnings("unchecked")
    private <T> Binder<T, ?, ?> getBinder(String channelName, Class<T> bindableType) {
        String binderConfigurationName = this.bindingServiceProperties.getBinder(channelName);
        return binderFactory.getBinder(binderConfigurationName, bindableType);
    }

    /**
     * Provided for backwards compatibility. Will be removed in a future version.
     *
     * @return
     */
    @Deprecated
    public BindingServiceProperties getChannelBindingServiceProperties() {
        return this.bindingServiceProperties;
    }

    public BindingServiceProperties getBindingServiceProperties() {
        return this.bindingServiceProperties;
    }

    private void validate(Object properties) {
        RelaxedDataBinder dataBinder = new RelaxedDataBinder(properties);
        dataBinder.setValidator(validator);
        dataBinder.validate();
        if (dataBinder.getBindingResult().hasErrors()) {
            throw new IllegalStateException(dataBinder.getBindingResult().toString());
        }
    }
}