001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.component.binding;
018
019import org.apache.camel.CamelContextAware;
020import org.apache.camel.Component;
021import org.apache.camel.Consumer;
022import org.apache.camel.Endpoint;
023import org.apache.camel.Exchange;
024import org.apache.camel.Processor;
025import org.apache.camel.Producer;
026import org.apache.camel.impl.DefaultEndpoint;
027import org.apache.camel.processor.PipelineHelper;
028import org.apache.camel.spi.Binding;
029import org.apache.camel.spi.HasBinding;
030import org.apache.camel.spi.Metadata;
031import org.apache.camel.spi.UriEndpoint;
032import org.apache.camel.spi.UriPath;
033import org.apache.camel.util.CamelContextHelper;
034import org.apache.camel.util.ServiceHelper;
035
036import static org.apache.camel.util.CamelContextHelper.getMandatoryEndpoint;
037
038/**
039 * The binding component is used for as a of wrapping an Endpoint in a contract with a data format.
040 *
041 * In Camel terms a binding is a way of wrapping an Endpoint in a contract; such as a Data Format,
042 * a Content Enricher or validation step. Bindings are completely optional and you can choose to use
043 * them on any camel endpoint.
044 * Bindings are inspired by the work of SwitchYard project adding service contracts to various technologies
045 * like Camel and many others. But rather than the SwitchYard approach of wrapping Camel in SCA,
046 * Camel Bindings provide a way of wrapping Camel endpoints with contracts inside the Camel framework itself;
047 * so you can use them easily inside any Camel route.
048 *
049 * Applies a {@link org.apache.camel.spi.Binding} to an underlying {@link Endpoint} so that the binding processes messages
050 * before its sent to the endpoint and processes messages received by the endpoint consumer before its passed
051 * to the real consumer.
052 */
053@UriEndpoint(scheme = "binding", title = "Binding", syntax = "binding:bindingName:delegateUri", consumerClass = BindingConsumerProcessor.class, label = "core,transformation")
054public class BindingEndpoint extends DefaultEndpoint implements HasBinding {
055
056    @UriPath @Metadata(required = "true")
057    private final String bindingName;
058    @UriPath @Metadata(required = "true")
059    private final String delegateUri;
060    private Binding binding;
061    private Endpoint delegate;
062
063    @Deprecated
064    public BindingEndpoint(String uri, Component component, Binding binding, Endpoint delegate) {
065        super(uri, component);
066        this.binding = binding;
067        this.delegate = delegate;
068        this.bindingName = null;
069        this.delegateUri = null;
070    }
071
072    public BindingEndpoint(String uri, Component component, String bindingName, String delegateUri) {
073        super(uri, component);
074        this.bindingName = bindingName;
075        this.delegateUri = delegateUri;
076    }
077
078    @Override
079    public Producer createProducer() throws Exception {
080        return new BindingProducer(this);
081    }
082
083    @Override
084    public Consumer createConsumer(Processor processor) throws Exception {
085        Processor bindingProcessor = new BindingConsumerProcessor(this, processor);
086        return delegate.createConsumer(bindingProcessor);
087    }
088
089    @Override
090    public boolean isSingleton() {
091        return true;
092    }
093
094    @Override
095    public Binding getBinding() {
096        return binding;
097    }
098
099    public Endpoint getDelegate() {
100        return delegate;
101    }
102
103    /**
104     * Name of the binding to lookup in the Camel registry.
105     */
106    public String getBindingName() {
107        return bindingName;
108    }
109
110    /**
111     * Uri of the delegate endpoint.
112     */
113    public String getDelegateUri() {
114        return delegateUri;
115    }
116
117    /**
118     * Applies the {@link Binding} processor to the given exchange before passing it on to the delegateProcessor (either a producer or consumer)
119     */
120    public void pipelineBindingProcessor(Processor bindingProcessor, Exchange exchange, Processor delegateProcessor) throws Exception {
121        bindingProcessor.process(exchange);
122
123        Exchange delegateExchange = PipelineHelper.createNextExchange(exchange);
124        delegateProcessor.process(delegateExchange);
125    }
126
127    @Override
128    protected void doStart() throws Exception {
129        if (binding == null) {
130            binding = CamelContextHelper.mandatoryLookup(getCamelContext(), bindingName, Binding.class);
131        }
132        if (delegate == null) {
133            delegate = getMandatoryEndpoint(getCamelContext(), delegateUri);
134        }
135
136        // inject CamelContext
137        if (binding instanceof CamelContextAware) {
138            ((CamelContextAware) binding).setCamelContext(getCamelContext());
139        }
140        ServiceHelper.startServices(delegate, binding);
141        super.doStart();
142    }
143
144    @Override
145    protected void doStop() throws Exception {
146        ServiceHelper.stopServices(delegate, binding);
147        super.doStop();
148    }
149}