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     */
017    package org.apache.camel.impl;
018    
019    import java.util.HashMap;
020    import java.util.Map;
021    
022    import org.apache.camel.AsyncCallback;
023    import org.apache.camel.CamelContext;
024    import org.apache.camel.Endpoint;
025    import org.apache.camel.Exchange;
026    import org.apache.camel.ExchangePattern;
027    import org.apache.camel.Message;
028    import org.apache.camel.NoSuchEndpointException;
029    import org.apache.camel.Processor;
030    import org.apache.camel.Producer;
031    import org.apache.camel.ProducerTemplate;
032    import org.apache.camel.util.ObjectHelper;
033    
034    /**
035     * A client helper object (named like Spring's TransactionTemplate & JmsTemplate
036     * et al) for working with Camel and sending {@link org.apache.camel.Message} instances in an
037     * {@link org.apache.camel.Exchange} to an {@link org.apache.camel.Endpoint}.
038     *
039     * @version $Revision: 44269 $
040     */
041    public class DefaultProducerTemplate<E extends Exchange> extends ServiceSupport implements ProducerTemplate<E> {
042        private CamelContext context;
043        private final ProducerCache<E> producerCache = new ProducerCache<E>();
044        private boolean useEndpointCache = true;
045        private final Map<String, Endpoint<E>> endpointCache = new HashMap<String, Endpoint<E>>();
046        private Endpoint<E> defaultEndpoint;
047    
048        public DefaultProducerTemplate(CamelContext context) {
049            this.context = context;
050        }
051    
052        public DefaultProducerTemplate(CamelContext context, Endpoint defaultEndpoint) {
053            this(context);
054            this.defaultEndpoint = defaultEndpoint;
055        }
056    
057        public E send(String endpointUri, E exchange) {
058            Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
059            return send(endpoint, exchange);
060        }
061    
062        public E send(String endpointUri, Processor processor) {
063            Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
064            return send(endpoint, processor);
065        }
066    
067        public E send(String endpointUri, Processor processor, AsyncCallback callback) {
068            Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
069            return send(endpoint, processor, callback);
070        }
071    
072        public E send(String endpointUri, ExchangePattern pattern, Processor processor) {
073            Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
074            return send(endpoint, pattern, processor);
075        }
076    
077        public E send(Endpoint<E> endpoint, E exchange) {
078            E convertedExchange = exchange;
079            producerCache.send(endpoint, convertedExchange);
080            return convertedExchange;
081        }
082    
083        public E send(Endpoint<E> endpoint, Processor processor) {
084            return producerCache.send(endpoint, processor);
085        }
086    
087        public E send(Endpoint<E> endpoint, Processor processor, AsyncCallback callback) {
088            return producerCache.send(endpoint, processor, callback);
089        }
090    
091        public E send(Endpoint<E> endpoint, ExchangePattern pattern, Processor processor) {
092            return producerCache.send(endpoint, pattern, processor);
093        }
094    
095        public Object sendBody(Endpoint<E> endpoint, ExchangePattern pattern, Object body) {
096            E result = send(endpoint, pattern, createSetBodyProcessor(body));
097            return extractResultBody(result, pattern);
098        }
099    
100        public Object sendBody(Endpoint<E> endpoint, Object body) {
101            E result = send(endpoint, createSetBodyProcessor(body));
102            return extractResultBody(result);
103        }
104    
105        public Object sendBody(String endpointUri, Object body) {
106            Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
107            return sendBody(endpoint, body);
108        }
109    
110        public Object sendBody(String endpointUri, ExchangePattern pattern, Object body) {
111            Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
112            return sendBody(endpoint, pattern, body);
113        }
114    
115        public Object sendBodyAndHeader(String endpointUri, final Object body, final String header,
116                final Object headerValue) {
117            return sendBodyAndHeader(resolveMandatoryEndpoint(endpointUri), body, header, headerValue);
118        }
119    
120        public Object sendBodyAndHeader(Endpoint endpoint, final Object body, final String header,
121                final Object headerValue) {
122            E result = send(endpoint, createBodyAndHeaderProcessor(body, header, headerValue));
123            return extractResultBody(result);
124        }
125    
126        public Object sendBodyAndHeader(Endpoint endpoint, ExchangePattern pattern, final Object body, final String header,
127                final Object headerValue) {
128            E result = send(endpoint, pattern, createBodyAndHeaderProcessor(body, header, headerValue));
129            return extractResultBody(result, pattern);
130        }
131    
132        public Object sendBodyAndHeader(String endpoint, ExchangePattern pattern, final Object body, final String header,
133                final Object headerValue) {
134            E result = send(endpoint, pattern, createBodyAndHeaderProcessor(body, header, headerValue));
135            return extractResultBody(result, pattern);
136        }
137    
138        public Object sendBodyAndHeaders(String endpointUri, final Object body, final Map<String, Object> headers) {
139            return sendBodyAndHeaders(resolveMandatoryEndpoint(endpointUri), body, headers);
140        }
141    
142        public Object sendBodyAndHeaders(Endpoint endpoint, final Object body, final Map<String, Object> headers) {
143            E result = send(endpoint, new Processor() {
144                public void process(Exchange exchange) {
145                    Message in = exchange.getIn();
146                    for (Map.Entry<String, Object> header : headers.entrySet()) {
147                        in.setHeader(header.getKey(), header.getValue());
148                    }
149                    in.setBody(body);
150                }
151            });
152            return extractResultBody(result);
153        }
154    
155        // Methods using an InOut ExchangePattern
156        // -----------------------------------------------------------------------
157    
158        public E request(Endpoint<E> endpoint, Processor processor) {
159            return send(endpoint, ExchangePattern.InOut, processor);
160        }
161    
162        public Object requestBody(Endpoint<E> endpoint, Object body) {
163            return sendBody(endpoint, ExchangePattern.InOut, body);
164        }
165    
166        public Object requestBodyAndHeader(Endpoint<E> endpoint, Object body, String header, Object headerValue) {
167            return sendBodyAndHeader(endpoint, ExchangePattern.InOut, body, header, headerValue);
168        }
169    
170        public E request(String endpoint, Processor processor) {
171            return send(endpoint, ExchangePattern.InOut, processor);
172        }
173    
174        public Object requestBody(String endpoint, Object body) {
175            return sendBody(endpoint, ExchangePattern.InOut, body);
176        }
177    
178        public Object requestBodyAndHeader(String endpoint, Object body, String header, Object headerValue) {
179            return sendBodyAndHeader(endpoint, ExchangePattern.InOut, body, header, headerValue);
180        }
181    
182        // Methods using the default endpoint
183        // -----------------------------------------------------------------------
184    
185        public Object sendBody(Object body) {
186            return sendBody(getMandatoryDefaultEndpoint(), body);
187        }
188    
189        public E send(E exchange) {
190            return send(getMandatoryDefaultEndpoint(), exchange);
191        }
192    
193        public E send(Processor processor) {
194            return send(getMandatoryDefaultEndpoint(), processor);
195        }
196    
197        public Object sendBodyAndHeader(Object body, String header, Object headerValue) {
198            return sendBodyAndHeader(getMandatoryDefaultEndpoint(), body, header, headerValue);
199        }
200    
201        public Object sendBodyAndHeaders(Object body, Map<String, Object> headers) {
202            return sendBodyAndHeaders(getMandatoryDefaultEndpoint(), body, headers);
203        }
204    
205        // Properties
206        // -----------------------------------------------------------------------
207        public Producer<E> getProducer(Endpoint<E> endpoint) {
208            return producerCache.getProducer(endpoint);
209        }
210    
211        public CamelContext getContext() {
212            return context;
213        }
214    
215        public Endpoint<E> getDefaultEndpoint() {
216            return defaultEndpoint;
217        }
218    
219        public void setDefaultEndpoint(Endpoint<E> defaultEndpoint) {
220            this.defaultEndpoint = defaultEndpoint;
221        }
222    
223        /**
224         * Sets the default endpoint to use if none is specified
225         */
226        public void setDefaultEndpointUri(String endpointUri) {
227            setDefaultEndpoint(getContext().getEndpoint(endpointUri));
228        }
229    
230        public boolean isUseEndpointCache() {
231            return useEndpointCache;
232        }
233    
234        public void setUseEndpointCache(boolean useEndpointCache) {
235            this.useEndpointCache = useEndpointCache;
236        }
237    
238        public <T extends Endpoint<?>> T getResolvedEndpoint(String endpointUri, Class<T> expectedClass) {
239            Endpoint<?> e = null;
240            synchronized (endpointCache) {
241                e = endpointCache.get(endpointUri);
242            }
243            if (e != null && expectedClass.isAssignableFrom(e.getClass())) {
244                return expectedClass.asSubclass(expectedClass).cast(e);
245            }
246            return null;
247        }
248    
249        // Implementation methods
250        // -----------------------------------------------------------------------
251    
252        protected Processor createBodyAndHeaderProcessor(final Object body, final String header, final Object headerValue) {
253            return new Processor() {
254                public void process(Exchange exchange) {
255                    Message in = exchange.getIn();
256                    in.setHeader(header, headerValue);
257                    in.setBody(body);
258                }
259            };
260        }
261    
262        protected Processor createSetBodyProcessor(final Object body) {
263            return new Processor() {
264                public void process(Exchange exchange) {
265                    Message in = exchange.getIn();
266                    in.setBody(body);
267                }
268            };
269        }
270    
271        protected Endpoint resolveMandatoryEndpoint(String endpointUri) {
272            Endpoint endpoint = null;
273    
274            if (isUseEndpointCache()) {
275                synchronized (endpointCache) {
276                    endpoint = endpointCache.get(endpointUri);
277                    if (endpoint == null) {
278                        endpoint = context.getEndpoint(endpointUri);
279                        if (endpoint != null) {
280                            endpointCache.put(endpointUri, endpoint);
281                        }
282                    }
283                }
284            } else {
285                endpoint = context.getEndpoint(endpointUri);
286            }
287            if (endpoint == null) {
288                throw new NoSuchEndpointException(endpointUri);
289            }
290            return endpoint;
291        }
292    
293        protected Endpoint<E> getMandatoryDefaultEndpoint() {
294            Endpoint<E> answer = getDefaultEndpoint();
295            ObjectHelper.notNull(answer, "defaultEndpoint");
296            return answer;
297        }
298    
299        protected void doStart() throws Exception {
300            producerCache.start();
301        }
302    
303        protected void doStop() throws Exception {
304            producerCache.stop();
305            endpointCache.clear();
306        }
307    
308        /**
309         * Extracts the body from the given result.
310         *
311         * @param result   the result
312         * @return  the result, can be <tt>null</tt>.
313         */
314        protected Object extractResultBody(E result) {
315            return extractResultBody(result, null);
316        }
317    
318        /**
319         * Extracts the body from the given result.
320         * <p/>
321         * If the exchange pattern is provided it will try to honor it and retrive the body
322         * from either IN or OUT according to the pattern.
323         *
324         * @param result   the result
325         * @param pattern  exchange pattern if given, can be <tt>null</tt>
326         * @return  the result, can be <tt>null</tt>.
327         */
328        protected Object extractResultBody(E result, ExchangePattern pattern) {
329            Object answer = null;
330            if (result != null) {
331                // try to honor pattern if provided
332                boolean notOut = pattern != null && !pattern.isOutCapable();
333                boolean hasOut = result.getOut(false) != null;
334                if (hasOut && !notOut) {
335                    answer = result.getOut().getBody();
336                } else {
337                    answer = result.getIn().getBody();
338                }
339            }
340            return answer;
341        }
342    
343    }