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