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;
018    
019    import java.util.HashMap;
020    import java.util.Map;
021    
022    import org.apache.camel.impl.ServiceSupport;
023    import org.apache.camel.util.ObjectHelper;
024    import org.apache.camel.util.ProducerCache;
025    
026    /**
027     * A client helper object (named like Spring's TransactionTemplate & JmsTemplate
028     * et al) for working with Camel and sending {@link Message} instances in an
029     * {@link Exchange} to an {@link Endpoint}.
030     *
031     * @version $Revision: 642753 $
032     */
033    public class CamelTemplate<E extends Exchange> extends ServiceSupport implements ProducerTemplate<E> {
034        private CamelContext context;
035        private ProducerCache<E> producerCache = new ProducerCache<E>();
036        private boolean useEndpointCache = true;
037        private Map<String, Endpoint<E>> endpointCache = new HashMap<String, Endpoint<E>>();
038        private Endpoint<E> defaultEndpoint;
039    
040        public CamelTemplate(CamelContext context) {
041            this.context = context;
042        }
043    
044        public CamelTemplate(CamelContext context, Endpoint defaultEndpoint) {
045            this(context);
046            this.defaultEndpoint = defaultEndpoint;
047        }
048    
049        /**
050         * Sends the exchange to the given endpoint
051         *
052         * @param endpointUri the endpoint URI to send the exchange to
053         * @param exchange    the exchange to send
054         */
055        public E send(String endpointUri, E exchange) {
056            Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
057            return send(endpoint, exchange);
058        }
059    
060        /**
061         * Sends an exchange to an endpoint using a supplied
062         *
063         * @param endpointUri the endpoint URI to send the exchange to
064         * @param processor   the transformer used to populate the new exchange
065         * {@link Processor} to populate the exchange
066         */
067        public E send(String endpointUri, Processor processor) {
068            Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
069            return send(endpoint, processor);
070        }
071    
072        /**
073         * Sends an exchange to an endpoint using a supplied
074         *
075         * @param endpointUri the endpoint URI to send the exchange to
076         * @param processor   the transformer used to populate the new exchange
077         * {@link Processor} to populate the exchange.  The callback
078         * will be called when the exchange is completed.
079         */
080        public E send(String endpointUri, Processor processor, AsyncCallback callback) {
081            Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
082            return send(endpoint, processor, callback);
083        }
084    
085        /**
086         * Sends an exchange to an endpoint using a supplied
087         *
088         * @param endpointUri the endpoint URI to send the exchange to
089         * @param pattern     the message {@link ExchangePattern} such as
090         *                    {@link ExchangePattern#InOnly} or {@link ExchangePattern#InOut}
091         * @param processor   the transformer used to populate the new exchange
092         * {@link Processor} to populate the exchange
093         */
094        public E send(String endpointUri, ExchangePattern pattern, Processor processor) {
095            Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
096            return send(endpoint, pattern, processor);
097        }
098    
099        /**
100         * Sends the exchange to the given endpoint
101         *
102         * @param endpoint the endpoint to send the exchange to
103         * @param exchange the exchange to send
104         */
105        public E send(Endpoint<E> endpoint, E exchange) {
106            E convertedExchange = endpoint.createExchange(exchange);
107            producerCache.send(endpoint, convertedExchange);
108            return convertedExchange;
109        }
110    
111        /**
112         * Sends an exchange to an endpoint using a supplied
113         *
114         * @param endpoint  the endpoint to send the exchange to
115         * @param processor the transformer used to populate the new exchange
116         * {@link Processor} to populate the exchange
117         */
118        public E send(Endpoint<E> endpoint, Processor processor) {
119            return producerCache.send(endpoint, processor);
120        }
121    
122        /**
123         * Sends an exchange to an endpoint using a supplied
124         *
125         * @param endpoint  the endpoint to send the exchange to
126         * @param processor the transformer used to populate the new exchange
127         * {@link Processor} to populate the exchange.  The callback
128         * will be called when the exchange is completed.
129         */
130        public E send(Endpoint<E> endpoint, Processor processor, AsyncCallback callback) {
131            return producerCache.send(endpoint, processor, callback);
132        }
133    
134        /**
135         * Sends an exchange to an endpoint using a supplied
136         *
137         * @param endpoint  the endpoint to send the exchange to
138         * @param pattern   the message {@link ExchangePattern} such as
139         *                  {@link ExchangePattern#InOnly} or {@link ExchangePattern#InOut}
140         * @param processor the transformer used to populate the new exchange
141         * {@link Processor} to populate the exchange
142         */
143        public E send(Endpoint<E> endpoint, ExchangePattern pattern, Processor processor) {
144            return producerCache.send(endpoint, pattern, processor);
145        }
146    
147        /**
148         * Send the body to an endpoint with the given {@link ExchangePattern}
149         * returning any result output body
150         *
151         * @param endpoint
152         * @param body     = the payload
153         * @param pattern  the message {@link ExchangePattern} such as
154         *                 {@link ExchangePattern#InOnly} or {@link ExchangePattern#InOut}
155         * @return the result
156         */
157        public Object sendBody(Endpoint<E> endpoint, ExchangePattern pattern, Object body) {
158            E result = send(endpoint, pattern, createSetBodyProcessor(body));
159            return extractResultBody(result);
160        }
161    
162        /**
163         * Send the body to an endpoint returning any result output body
164         *
165         * @param endpoint
166         * @param body     = the payload
167         * @return the result
168         */
169        public Object sendBody(Endpoint<E> endpoint, Object body) {
170            E result = send(endpoint, createSetBodyProcessor(body));
171            return extractResultBody(result);
172        }
173    
174        /**
175         * Send the body to an endpoint
176         *
177         * @param endpointUri
178         * @param body        = the payload
179         * @return the result
180         */
181        public Object sendBody(String endpointUri, Object body) {
182            Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
183            return sendBody(endpoint, body);
184        }
185    
186        /**
187         * Send the body to an endpoint
188         *
189         * @param endpointUri
190         * @param pattern     the message {@link ExchangePattern} such as
191         *                    {@link ExchangePattern#InOnly} or {@link ExchangePattern#InOut}
192         * @param body        = the payload
193         * @return the result
194         */
195        public Object sendBody(String endpointUri, ExchangePattern pattern, Object body) {
196            Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
197            return sendBody(endpoint, pattern, body);
198        }
199    
200        /**
201         * Sends the body to an endpoint with a specified header and header value
202         *
203         * @param endpointUri the endpoint URI to send to
204         * @param body        the payload send
205         * @param header      the header name
206         * @param headerValue the header value
207         * @return the result
208         */
209        public Object sendBodyAndHeader(String endpointUri, final Object body, final String header,
210                final Object headerValue) {
211            return sendBodyAndHeader(resolveMandatoryEndpoint(endpointUri), body, header, headerValue);
212        }
213    
214        /**
215         * Sends the body to an endpoint with a specified header and header value
216         *
217         * @param endpoint    the Endpoint to send to
218         * @param body        the payload send
219         * @param header      the header name
220         * @param headerValue the header value
221         * @return the result
222         */
223        public Object sendBodyAndHeader(Endpoint endpoint, final Object body, final String header,
224                final Object headerValue) {
225            E result = send(endpoint, createBodyAndHeaderProcessor(body, header, headerValue));
226            return extractResultBody(result);
227        }
228    
229        /**
230         * Sends the body to an endpoint with a specified header and header value
231         *
232         * @param endpoint    the Endpoint to send to
233         * @param pattern     the message {@link ExchangePattern} such as
234         *                    {@link ExchangePattern#InOnly} or {@link ExchangePattern#InOut}
235         * @param body        the payload send
236         * @param header      the header name
237         * @param headerValue the header value
238         * @return the result
239         */
240        public Object sendBodyAndHeader(Endpoint endpoint, ExchangePattern pattern, final Object body, final String header,
241                final Object headerValue) {
242            E result = send(endpoint, pattern, createBodyAndHeaderProcessor(body, header, headerValue));
243            return extractResultBody(result);
244        }
245    
246        /**
247         * Sends the body to an endpoint with a specified header and header value
248         *
249         * @param endpoint    the Endpoint URI to send to
250         * @param pattern     the message {@link ExchangePattern} such as
251         *                    {@link ExchangePattern#InOnly} or {@link ExchangePattern#InOut}
252         * @param body        the payload send
253         * @param header      the header name
254         * @param headerValue the header value
255         * @return the result
256         */
257        public Object sendBodyAndHeader(String endpoint, ExchangePattern pattern, final Object body, final String header,
258                final Object headerValue) {
259            E result = send(endpoint, pattern, createBodyAndHeaderProcessor(body, header, headerValue));
260            return extractResultBody(result);
261        }
262    
263        /**
264         * Sends the body to an endpoint with the specified headers and header
265         * values
266         *
267         * @param endpointUri the endpoint URI to send to
268         * @param body        the payload send
269         * @return the result
270         */
271        public Object sendBodyAndHeaders(String endpointUri, final Object body, final Map<String, Object> headers) {
272            return sendBodyAndHeaders(resolveMandatoryEndpoint(endpointUri), body, headers);
273        }
274    
275        /**
276         * Sends the body to an endpoint with the specified headers and header
277         * values
278         *
279         * @param endpoint the endpoint URI to send to
280         * @param body     the payload send
281         * @return the result
282         */
283        public Object sendBodyAndHeaders(Endpoint endpoint, final Object body, final Map<String, Object> headers) {
284            E result = send(endpoint, new Processor() {
285                public void process(Exchange exchange) {
286                    Message in = exchange.getIn();
287                    for (Map.Entry<String, Object> header : headers.entrySet()) {
288                        in.setHeader(header.getKey(), header.getValue());
289                    }
290                    in.setBody(body);
291                }
292            });
293            return extractResultBody(result);
294        }
295    
296        // Methods using an InOut ExchangePattern
297        // -----------------------------------------------------------------------
298    
299        /**
300         * Send the body to an endpoint returning any result output body
301         *
302         * @param endpoint
303         * @param processor the processor which will populate the exchange before sending
304         * @return the result
305         */
306        public E request(Endpoint<E> endpoint, Processor processor) {
307            return send(endpoint, ExchangePattern.InOut, processor);
308        }
309    
310        /**
311         * Send the body to an endpoint returning any result output body
312         *
313         * @param endpoint
314         * @param body     = the payload
315         * @return the result
316         */
317        public Object requestBody(Endpoint<E> endpoint, Object body) {
318            return sendBody(endpoint, ExchangePattern.InOut, body);
319        }
320    
321        /**
322         * Send the body to an endpoint returning any result output body
323         *
324         * @param endpoint
325         * @param body        = the payload
326         * @param header
327         * @param headerValue
328         * @return the result
329         */
330        public Object requestBodyAndHeader(Endpoint<E> endpoint, Object body, String header, Object headerValue) {
331            return sendBodyAndHeader(endpoint, ExchangePattern.InOut, body, header, headerValue);
332        }
333    
334        /**
335         * Send the body to an endpoint returning any result output body
336         *
337         * @param endpoint
338         * @param processor the processor which will populate the exchange before sending
339         * @return the result
340         */
341        public E request(String endpoint, Processor processor) {
342            return send(endpoint, ExchangePattern.InOut, processor);
343        }
344    
345        /**
346         * Send the body to an endpoint returning any result output body
347         *
348         * @param endpoint
349         * @param body     = the payload
350         * @return the result
351         */
352        public Object requestBody(String endpoint, Object body) {
353            return sendBody(endpoint, ExchangePattern.InOut, body);
354        }
355    
356        /**
357         * Send the body to an endpoint returning any result output body
358         *
359         * @param endpoint
360         * @param body        = the payload
361         * @param header
362         * @param headerValue
363         * @return the result
364         */
365        public Object requestBodyAndHeader(String endpoint, Object body, String header, Object headerValue) {
366            return sendBodyAndHeader(endpoint, ExchangePattern.InOut, body, header, headerValue);
367        }
368    
369        // Methods using the default endpoint
370        // -----------------------------------------------------------------------
371    
372        /**
373         * Sends the body to the default endpoint and returns the result content
374         *
375         * @param body the body to send
376         * @return the returned message body
377         */
378        public Object sendBody(Object body) {
379            return sendBody(getMandatoryDefaultEndpoint(), body);
380        }
381    
382        /**
383         * Sends the exchange to the default endpoint
384         *
385         * @param exchange the exchange to send
386         */
387        public E send(E exchange) {
388            return send(getMandatoryDefaultEndpoint(), exchange);
389        }
390    
391        /**
392         * Sends an exchange to the default endpoint using a supplied
393         *
394         * @param processor the transformer used to populate the new exchange
395         * {@link Processor} to populate the exchange
396         */
397        public E send(Processor processor) {
398            return send(getMandatoryDefaultEndpoint(), processor);
399        }
400    
401        public Object sendBodyAndHeader(Object body, String header, Object headerValue) {
402            return sendBodyAndHeader(getMandatoryDefaultEndpoint(), body, header, headerValue);
403        }
404    
405        public Object sendBodyAndHeaders(Object body, Map<String, Object> headers) {
406            return sendBodyAndHeaders(getMandatoryDefaultEndpoint(), body, headers);
407        }
408    
409        // Properties
410        // -----------------------------------------------------------------------
411        public Producer<E> getProducer(Endpoint<E> endpoint) {
412            return producerCache.getProducer(endpoint);
413        }
414    
415        public CamelContext getContext() {
416            return context;
417        }
418    
419        public Endpoint<E> getDefaultEndpoint() {
420            return defaultEndpoint;
421        }
422    
423        public void setDefaultEndpoint(Endpoint<E> defaultEndpoint) {
424            this.defaultEndpoint = defaultEndpoint;
425        }
426    
427        /**
428         * Sets the default endpoint to use if none is specified
429         */
430        public void setDefaultEndpointUri(String endpointUri) {
431            setDefaultEndpoint(getContext().getEndpoint(endpointUri));
432        }
433    
434        public boolean isUseEndpointCache() {
435            return useEndpointCache;
436        }
437    
438        public void setUseEndpointCache(boolean useEndpointCache) {
439            this.useEndpointCache = useEndpointCache;
440        }
441    
442        // Implementation methods
443        // -----------------------------------------------------------------------
444    
445        protected Processor createBodyAndHeaderProcessor(final Object body, final String header, final Object headerValue) {
446            return new Processor() {
447                public void process(Exchange exchange) {
448                    Message in = exchange.getIn();
449                    in.setHeader(header, headerValue);
450                    in.setBody(body);
451                }
452            };
453        }
454    
455        protected Processor createSetBodyProcessor(final Object body) {
456            return new Processor() {
457                public void process(Exchange exchange) {
458                    Message in = exchange.getIn();
459                    in.setBody(body);
460                }
461            };
462        }
463    
464        protected Endpoint resolveMandatoryEndpoint(String endpointUri) {
465            Endpoint endpoint = null;
466    
467            if (isUseEndpointCache()) {
468                synchronized (endpointCache) {
469                    endpoint = endpointCache.get(endpointUri);
470                    if (endpoint == null) {
471                        endpoint = context.getEndpoint(endpointUri);
472                        if (endpoint != null) {
473                            endpointCache.put(endpointUri, endpoint);
474                        }
475                    }
476                }
477            } else {
478                endpoint = context.getEndpoint(endpointUri);
479            }
480            if (endpoint == null) {
481                throw new NoSuchEndpointException(endpointUri);
482            }
483            return endpoint;
484        }
485    
486        protected Endpoint<E> getMandatoryDefaultEndpoint() {
487            Endpoint<E> answer = getDefaultEndpoint();
488            ObjectHelper.notNull(answer, "defaultEndpoint");
489            return answer;
490        }
491    
492        protected void doStart() throws Exception {
493            producerCache.start();
494        }
495    
496        protected void doStop() throws Exception {
497            producerCache.stop();
498        }
499    
500        protected Object extractResultBody(E result) {
501            Object answer = null;
502            if (result != null) {
503                Message out = result.getOut(false);
504                if (out != null) {
505                    answer = out.getBody();
506                } else {
507                    answer = result.getIn().getBody();
508                }
509            }
510            return answer;
511        }
512    }