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 }