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.CamelContextHelper;
033 import org.apache.camel.util.ObjectHelper;
034
035 import static org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException;
036
037 /**
038 * A client helper object (named like Spring's TransactionTemplate & JmsTemplate
039 * et al) for working with Camel and sending {@link org.apache.camel.Message} instances in an
040 * {@link org.apache.camel.Exchange} to an {@link org.apache.camel.Endpoint}.
041 *
042 * @version $Revision: 750400 $
043 */
044 public class DefaultProducerTemplate extends ServiceSupport implements ProducerTemplate {
045 private final CamelContext context;
046 private final ProducerCache producerCache = new ProducerCache();
047 private boolean useEndpointCache = true;
048 private final Map<String, Endpoint> endpointCache = new HashMap<String, Endpoint>();
049 private Endpoint defaultEndpoint;
050
051 public DefaultProducerTemplate(CamelContext context) {
052 this.context = context;
053 }
054
055 public DefaultProducerTemplate(CamelContext context, Endpoint defaultEndpoint) {
056 this(context);
057 this.defaultEndpoint = defaultEndpoint;
058 }
059
060 public static DefaultProducerTemplate newInstance(CamelContext camelContext, String defaultEndpointUri) {
061 Endpoint endpoint = CamelContextHelper.getMandatoryEndpoint(camelContext, defaultEndpointUri);
062 return new DefaultProducerTemplate(camelContext, endpoint);
063 }
064
065 public Exchange send(String endpointUri, Exchange exchange) {
066 Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
067 return send(endpoint, exchange);
068 }
069
070 public Exchange send(String endpointUri, Processor processor) {
071 Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
072 return send(endpoint, processor);
073 }
074
075 public Exchange send(String endpointUri, Processor processor, AsyncCallback callback) {
076 Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
077 return send(endpoint, processor, callback);
078 }
079
080 public Exchange send(String endpointUri, ExchangePattern pattern, Processor processor) {
081 Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
082 return send(endpoint, pattern, processor);
083 }
084
085 public Exchange send(Endpoint endpoint, Exchange exchange) {
086 producerCache.send(endpoint, exchange);
087 return exchange;
088 }
089
090 public Exchange send(Endpoint endpoint, Processor processor) {
091 return producerCache.send(endpoint, processor);
092 }
093
094 public Exchange send(Endpoint endpoint, Processor processor, AsyncCallback callback) {
095 return producerCache.send(endpoint, processor, callback);
096 }
097
098 public Exchange send(Endpoint endpoint, ExchangePattern pattern, Processor processor) {
099 return producerCache.send(endpoint, pattern, processor);
100 }
101
102 public Object sendBody(Endpoint endpoint, ExchangePattern pattern, Object body) {
103 Exchange result = send(endpoint, pattern, createSetBodyProcessor(body));
104 return extractResultBody(result, pattern);
105 }
106
107 public Object sendBody(Endpoint endpoint, Object body) {
108 Exchange result = send(endpoint, createSetBodyProcessor(body));
109 return extractResultBody(result);
110 }
111
112 public Object sendBody(String endpointUri, Object body) {
113 Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
114 return sendBody(endpoint, body);
115 }
116
117 public Object sendBody(String endpointUri, ExchangePattern pattern, Object body) {
118 Endpoint endpoint = resolveMandatoryEndpoint(endpointUri);
119 return sendBody(endpoint, pattern, body);
120 }
121
122 public Object sendBodyAndHeader(String endpointUri, final Object body, final String header,
123 final Object headerValue) {
124 return sendBodyAndHeader(resolveMandatoryEndpoint(endpointUri), body, header, headerValue);
125 }
126
127 public Object sendBodyAndHeader(Endpoint endpoint, final Object body, final String header,
128 final Object headerValue) {
129 Exchange result = send(endpoint, createBodyAndHeaderProcessor(body, header, headerValue));
130 return extractResultBody(result);
131 }
132
133 public Object sendBodyAndHeader(Endpoint endpoint, ExchangePattern pattern, final Object body, final String header,
134 final Object headerValue) {
135 Exchange result = send(endpoint, pattern, createBodyAndHeaderProcessor(body, header, headerValue));
136 return extractResultBody(result, pattern);
137 }
138
139 public Object sendBodyAndHeader(String endpoint, ExchangePattern pattern, final Object body, final String header,
140 final Object headerValue) {
141 Exchange result = send(endpoint, pattern, createBodyAndHeaderProcessor(body, header, headerValue));
142 return extractResultBody(result, pattern);
143 }
144
145 public Object sendBodyAndProperty(String endpointUri, final Object body, final String property,
146 final Object propertyValue) {
147 return sendBodyAndProperty(resolveMandatoryEndpoint(endpointUri), body, property, propertyValue);
148 }
149
150 public Object sendBodyAndProperty(Endpoint endpoint, final Object body, final String property,
151 final Object propertyValue) {
152 Exchange result = send(endpoint, createBodyAndPropertyProcessor(body, property, propertyValue));
153 return extractResultBody(result);
154 }
155
156 public Object sendBodyAndProperty(Endpoint endpoint, ExchangePattern pattern, final Object body, final String property,
157 final Object propertyValue) {
158 Exchange result = send(endpoint, pattern, createBodyAndPropertyProcessor(body, property, propertyValue));
159 return extractResultBody(result, pattern);
160 }
161
162 public Object sendBodyAndProperty(String endpoint, ExchangePattern pattern, final Object body, final String property,
163 final Object propertyValue) {
164 Exchange result = send(endpoint, pattern, createBodyAndPropertyProcessor(body, property, propertyValue));
165 return extractResultBody(result, pattern);
166 }
167
168 public Object sendBodyAndHeaders(String endpointUri, final Object body, final Map<String, Object> headers) {
169 return sendBodyAndHeaders(resolveMandatoryEndpoint(endpointUri), body, headers);
170 }
171
172 public Object sendBodyAndHeaders(Endpoint endpoint, final Object body, final Map<String, Object> headers) {
173 Exchange result = send(endpoint, new Processor() {
174 public void process(Exchange exchange) {
175 Message in = exchange.getIn();
176 for (Map.Entry<String, Object> header : headers.entrySet()) {
177 in.setHeader(header.getKey(), header.getValue());
178 }
179 in.setBody(body);
180 }
181 });
182 return extractResultBody(result);
183 }
184
185 public Object sendBodyAndHeaders(String endpointUri, ExchangePattern pattern, Object body, Map<String, Object> headers) {
186 return sendBodyAndHeaders(resolveMandatoryEndpoint(endpointUri), pattern, body, headers);
187 }
188
189 public Object sendBodyAndHeaders(Endpoint endpoint, ExchangePattern pattern, final Object body, final Map<String, Object> headers) {
190 Exchange result = send(endpoint, pattern, new Processor() {
191 public void process(Exchange exchange) throws Exception {
192 Message in = exchange.getIn();
193 for (Map.Entry<String, Object> header : headers.entrySet()) {
194 in.setHeader(header.getKey(), header.getValue());
195 }
196 in.setBody(body);
197 }
198 });
199 return extractResultBody(result);
200 }
201
202 // Methods using an InOut ExchangePattern
203 // -----------------------------------------------------------------------
204
205 public Exchange request(Endpoint endpoint, Processor processor) {
206 return send(endpoint, ExchangePattern.InOut, processor);
207 }
208
209 public Object requestBody(Object body) {
210 return sendBody(getMandatoryDefaultEndpoint(), ExchangePattern.InOut, body);
211 }
212
213 public Object requestBody(Endpoint endpoint, Object body) {
214 return sendBody(endpoint, ExchangePattern.InOut, body);
215 }
216
217 public Object requestBodyAndHeader(Endpoint endpoint, Object body, String header, Object headerValue) {
218 return sendBodyAndHeader(endpoint, ExchangePattern.InOut, body, header, headerValue);
219 }
220
221 public Exchange request(String endpoint, Processor processor) {
222 return send(endpoint, ExchangePattern.InOut, processor);
223 }
224
225 public Object requestBody(String endpoint, Object body) {
226 return sendBody(endpoint, ExchangePattern.InOut, body);
227 }
228
229 public Object requestBodyAndHeader(String endpoint, Object body, String header, Object headerValue) {
230 return sendBodyAndHeader(endpoint, ExchangePattern.InOut, body, header, headerValue);
231 }
232
233 public Object requestBodyAndHeaders(String endpointUri, Object body, Map<String, Object> headers) {
234 return requestBodyAndHeaders(resolveMandatoryEndpoint(endpointUri), body, headers);
235 }
236
237 public Object requestBodyAndHeaders(Endpoint endpoint, final Object body, final Map<String, Object> headers) {
238 return sendBodyAndHeaders(endpoint, ExchangePattern.InOut, body, headers);
239 }
240
241 // Methods using the default endpoint
242 // -----------------------------------------------------------------------
243
244 public Object sendBody(Object body) {
245 return sendBody(getMandatoryDefaultEndpoint(), body);
246 }
247
248 public Exchange send(Exchange exchange) {
249 return send(getMandatoryDefaultEndpoint(), exchange);
250 }
251
252 public Exchange send(Processor processor) {
253 return send(getMandatoryDefaultEndpoint(), processor);
254 }
255
256 public Object sendBodyAndHeader(Object body, String header, Object headerValue) {
257 return sendBodyAndHeader(getMandatoryDefaultEndpoint(), body, header, headerValue);
258 }
259
260 public Object sendBodyAndProperty(Object body, String property, Object propertyValue) {
261 return sendBodyAndProperty(getMandatoryDefaultEndpoint(), body, property, propertyValue);
262 }
263
264 public Object sendBodyAndHeaders(Object body, Map<String, Object> headers) {
265 return sendBodyAndHeaders(getMandatoryDefaultEndpoint(), body, headers);
266 }
267
268 // Properties
269 // -----------------------------------------------------------------------
270 public Producer getProducer(Endpoint endpoint) {
271 return producerCache.getProducer(endpoint);
272 }
273
274 public CamelContext getContext() {
275 return context;
276 }
277
278 public Endpoint getDefaultEndpoint() {
279 return defaultEndpoint;
280 }
281
282 public void setDefaultEndpoint(Endpoint defaultEndpoint) {
283 this.defaultEndpoint = defaultEndpoint;
284 }
285
286 /**
287 * Sets the default endpoint to use if none is specified
288 */
289 public void setDefaultEndpointUri(String endpointUri) {
290 setDefaultEndpoint(getContext().getEndpoint(endpointUri));
291 }
292
293 public boolean isUseEndpointCache() {
294 return useEndpointCache;
295 }
296
297 public void setUseEndpointCache(boolean useEndpointCache) {
298 this.useEndpointCache = useEndpointCache;
299 }
300
301 public <T extends Endpoint> T getResolvedEndpoint(String endpointUri, Class<T> expectedClass) {
302 Endpoint e;
303 synchronized (endpointCache) {
304 e = endpointCache.get(endpointUri);
305 }
306 if (e != null && expectedClass.isAssignableFrom(e.getClass())) {
307 return expectedClass.asSubclass(expectedClass).cast(e);
308 }
309 return null;
310 }
311
312 // Implementation methods
313 // -----------------------------------------------------------------------
314
315 protected Processor createBodyAndHeaderProcessor(final Object body, final String header, final Object headerValue) {
316 return new Processor() {
317 public void process(Exchange exchange) {
318 Message in = exchange.getIn();
319 in.setHeader(header, headerValue);
320 in.setBody(body);
321 }
322 };
323 }
324
325 protected Processor createBodyAndPropertyProcessor(final Object body, final String property, final Object propertyValue) {
326 return new Processor() {
327 public void process(Exchange exchange) {
328 exchange.setProperty(property, propertyValue);
329
330 Message in = exchange.getIn();
331 in.setBody(body);
332 }
333 };
334 }
335
336 protected Processor createSetBodyProcessor(final Object body) {
337 return new Processor() {
338 public void process(Exchange exchange) {
339 Message in = exchange.getIn();
340 in.setBody(body);
341 }
342 };
343 }
344
345 protected Endpoint resolveMandatoryEndpoint(String endpointUri) {
346 Endpoint endpoint;
347
348 if (isUseEndpointCache()) {
349 synchronized (endpointCache) {
350 endpoint = endpointCache.get(endpointUri);
351 if (endpoint == null) {
352 endpoint = context.getEndpoint(endpointUri);
353 if (endpoint != null) {
354 endpointCache.put(endpointUri, endpoint);
355 }
356 }
357 }
358 } else {
359 endpoint = context.getEndpoint(endpointUri);
360 }
361 if (endpoint == null) {
362 throw new NoSuchEndpointException(endpointUri);
363 }
364 return endpoint;
365 }
366
367 protected Endpoint getMandatoryDefaultEndpoint() {
368 Endpoint answer = getDefaultEndpoint();
369 ObjectHelper.notNull(answer, "defaultEndpoint");
370 return answer;
371 }
372
373 protected void doStart() throws Exception {
374 producerCache.start();
375 }
376
377 protected void doStop() throws Exception {
378 producerCache.stop();
379 endpointCache.clear();
380 }
381
382 /**
383 * Extracts the body from the given result.
384 *
385 * @param result the result
386 * @return the result, can be <tt>null</tt>.
387 */
388 protected Object extractResultBody(Exchange result) {
389 return extractResultBody(result, null);
390 }
391
392 /**
393 * Extracts the body from the given result.
394 * <p/>
395 * If the exchange pattern is provided it will try to honor it and retrive the body
396 * from either IN or OUT according to the pattern.
397 *
398 * @param result the result
399 * @param pattern exchange pattern if given, can be <tt>null</tt>
400 * @return the result, can be <tt>null</tt>.
401 */
402 protected Object extractResultBody(Exchange result, ExchangePattern pattern) {
403 Object answer = null;
404 if (result != null) {
405 // rethrow if there was an exception
406 if (result.getException() != null) {
407 throw wrapRuntimeCamelException(result.getException());
408 }
409
410 // result could have a fault message
411 if (hasFaultMessage(result)) {
412 return result.getFault().getBody();
413 }
414
415 // okay no fault then return the response according to the pattern
416 // try to honor pattern if provided
417 boolean notOut = pattern != null && !pattern.isOutCapable();
418 boolean hasOut = result.getOut(false) != null;
419 if (hasOut && !notOut) {
420 // we have a response in out and the pattern is out capable
421 answer = result.getOut().getBody();
422 } else if (!hasOut && result.getPattern() == ExchangePattern.InOptionalOut) {
423 // special case where the result is InOptionalOut and with no OUT response
424 // so we should return null to indicate this fact
425 answer = null;
426 } else {
427 // use IN as the response
428 answer = result.getIn().getBody();
429 }
430 }
431 return answer;
432 }
433
434 protected boolean hasFaultMessage(Exchange result) {
435 Message faultMessage = result.getFault(false);
436 if (faultMessage != null) {
437 Object faultBody = faultMessage.getBody();
438 if (faultBody != null) {
439 return true;
440 }
441 }
442 return false;
443 }
444 }