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