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