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.util;
018
019 import java.util.HashMap;
020 import java.util.Map;
021
022 import org.apache.camel.CamelContext;
023 import org.apache.camel.Endpoint;
024 import org.apache.camel.Exchange;
025 import org.apache.camel.ExchangePattern;
026 import org.apache.camel.InvalidPayloadException;
027 import org.apache.camel.InvalidTypeException;
028 import org.apache.camel.Message;
029 import org.apache.camel.NoSuchBeanException;
030 import org.apache.camel.NoSuchEndpointException;
031 import org.apache.camel.NoSuchHeaderException;
032 import org.apache.camel.NoSuchPropertyException;
033 import org.apache.camel.NoTypeConversionAvailableException;
034 import org.apache.camel.TypeConverter;
035 import org.apache.commons.logging.Log;
036 import org.apache.commons.logging.LogFactory;
037
038 /**
039 * Some helper methods for working with {@link Exchange} objects
040 *
041 * @version $Revision: 752532 $
042 */
043 public final class ExchangeHelper {
044 private static final transient Log LOG = LogFactory.getLog(ExchangeHelper.class);
045
046 /**
047 * Utility classes should not have a public constructor.
048 */
049 private ExchangeHelper() {
050 }
051
052 /**
053 * Extracts the exchange property of the given name and type; if it is not present then the
054 * default value will be used
055 *
056 * @param exchange the message exchange
057 * @param propertyName the name of the property on the exchange
058 * @param type the expected type of the property
059 * @param defaultValue the default value to be used if the property name does not exist or could not be
060 * converted to the given type
061 * @return the property value as the given type or the defaultValue if it could not be found or converted
062 */
063 public static <T> T getExchangeProperty(Exchange exchange, String propertyName, Class<T> type, T defaultValue) {
064 T answer = exchange.getProperty(propertyName, type);
065 if (answer == null) {
066 return defaultValue;
067 }
068 return answer;
069 }
070
071
072 /**
073 * Attempts to resolve the endpoint for the given value
074 *
075 * @param exchange the message exchange being processed
076 * @param value the value which can be an {@link Endpoint} or an object
077 * which provides a String representation of an endpoint via
078 * {@link #toString()}
079 *
080 * @return the endpoint
081 * @throws NoSuchEndpointException if the endpoint cannot be resolved
082 */
083 @SuppressWarnings({"unchecked" })
084 public static Endpoint resolveEndpoint(Exchange exchange, Object value)
085 throws NoSuchEndpointException {
086 Endpoint endpoint;
087 if (value instanceof Endpoint) {
088 endpoint = (Endpoint)value;
089 } else {
090 String uri = value.toString();
091 endpoint = CamelContextHelper.getMandatoryEndpoint(exchange.getContext(), uri);
092 }
093 return endpoint;
094 }
095
096 public static <T> T getMandatoryProperty(Exchange exchange, String propertyName, Class<T> type)
097 throws NoSuchPropertyException {
098 try {
099 T result = exchange.getProperty(propertyName, type);
100 if (result != null) {
101 return result;
102 }
103 } catch (NoTypeConversionAvailableException ex) {
104 // will throw NoSuchPropertyException below
105 }
106 throw new NoSuchPropertyException(exchange, propertyName, type);
107 }
108
109 public static <T> T getMandatoryHeader(Exchange exchange, String propertyName, Class<T> type)
110 throws NoSuchHeaderException {
111 T answer = exchange.getIn().getHeader(propertyName, type);
112 if (answer == null) {
113 throw new NoSuchHeaderException(exchange, propertyName, type);
114 }
115 return answer;
116 }
117
118 /**
119 * Returns the mandatory inbound message body of the correct type or throws
120 * an exception if it is not present
121 */
122 public static Object getMandatoryInBody(Exchange exchange) throws InvalidPayloadException {
123 Object answer = exchange.getIn().getBody();
124 if (answer == null) {
125 throw new InvalidPayloadException(exchange, Object.class);
126 }
127 return answer;
128 }
129
130 /**
131 * Returns the mandatory inbound message body of the correct type or throws
132 * an exception if it is not present
133 */
134 public static <T> T getMandatoryInBody(Exchange exchange, Class<T> type) throws InvalidPayloadException {
135 T answer = exchange.getIn().getBody(type);
136 if (answer == null) {
137 throw new InvalidPayloadException(exchange, type);
138 }
139 return answer;
140 }
141
142 /**
143 * Returns the mandatory outbound message body of the correct type or throws
144 * an exception if it is not present
145 */
146 public static Object getMandatoryOutBody(Exchange exchange) throws InvalidPayloadException {
147 Message out = exchange.getOut();
148 Object answer = out.getBody();
149 if (answer == null) {
150 throw new InvalidPayloadException(exchange, Object.class, out);
151 }
152 return answer;
153 }
154
155 /**
156 * Returns the mandatory outbound message body of the correct type or throws
157 * an exception if it is not present
158 */
159 public static <T> T getMandatoryOutBody(Exchange exchange, Class<T> type) throws InvalidPayloadException {
160 Message out = exchange.getOut();
161 T answer = out.getBody(type);
162 if (answer == null) {
163 throw new InvalidPayloadException(exchange, type, out);
164 }
165 return answer;
166 }
167
168 /**
169 * Converts the value to the given expected type or throws an exception
170 */
171 public static <T> T convertToMandatoryType(Exchange exchange, Class<T> type, Object value)
172 throws InvalidTypeException {
173 T answer = convertToType(exchange, type, value);
174 if (answer == null) {
175 throw new InvalidTypeException(exchange, value, type);
176 }
177 return answer;
178 }
179
180 /**
181 * Converts the value to the given expected type returning null if it could
182 * not be converted
183 */
184 public static <T> T convertToType(Exchange exchange, Class<T> type, Object value) {
185 CamelContext camelContext = exchange.getContext();
186 if (camelContext != null) {
187 TypeConverter converter = camelContext.getTypeConverter();
188 if (converter != null) {
189 return converter.convertTo(type, exchange, value);
190 }
191 }
192 LOG.warn("No CamelContext and type converter available to convert types for exchange " + exchange);
193
194 if (type.isInstance(value)) {
195 return type.cast(value);
196 }
197 return null;
198 }
199
200 /**
201 * Copies the results of a message exchange from the source exchange to the result exchange
202 * which will copy the out and fault message contents and the exception
203 *
204 * @param result the result exchange which will have the output and error state added
205 * @param source the source exchange which is not modified
206 */
207 public static void copyResults(Exchange result, Exchange source) {
208
209 // --------------------------------------------------------------------
210 // TODO: merge logic with that of copyResultsPreservePattern()
211 // --------------------------------------------------------------------
212
213 if (result != source) {
214 result.setException(source.getException());
215 Message fault = source.getFault(false);
216 if (fault != null) {
217 result.getFault(true).copyFrom(fault);
218 }
219
220 Message out = source.getOut(false);
221 if (out != null) {
222 result.getOut(true).copyFrom(out);
223 } else if (result.getPattern() == ExchangePattern.InOptionalOut) {
224 // special case where the result is InOptionalOut and with no OUT response
225 // so we should return null to indicate this fact
226 result.setOut(null);
227 } else {
228 // no results so lets copy the last input
229 // as the final processor on a pipeline might not
230 // have created any OUT; such as a mock:endpoint
231 // so lets assume the last IN is the OUT
232 if (result.getPattern().isOutCapable()) {
233 // only set OUT if its OUT capable
234 result.getOut(true).copyFrom(source.getIn());
235 } else {
236 // if not replace IN instead to keep the MEP
237 result.getIn().copyFrom(source.getIn());
238 }
239 }
240 result.getProperties().clear();
241 result.getProperties().putAll(source.getProperties());
242 }
243 }
244
245 /**
246 * Copies the <code>source</code> exchange to <code>target</code> exchange
247 * preserving the {@link ExchangePattern} of <code>target</code>.
248 *
249 * @param source source exchange.
250 * @param result target exchange.
251 */
252 public static void copyResultsPreservePattern(Exchange result, Exchange source) {
253
254 // --------------------------------------------------------------------
255 // TODO: merge logic with that of copyResults()
256 // --------------------------------------------------------------------
257
258 if (source == result) {
259 // no need to copy
260 return;
261 }
262
263 // copy in message
264 Message m = source.getIn();
265 result.getIn().copyFrom(m);
266
267 // copy out message
268 m = source.getOut(false);
269 if (m != null) {
270 // exchange pattern sensitive
271 getResultMessage(result).copyFrom(m);
272 }
273
274 // copy fault message
275 m = source.getFault(false);
276 if (m != null) {
277 result.getFault().copyFrom(m);
278 }
279
280 // copy exception
281 result.setException(source.getException());
282
283 // copy properties
284 result.getProperties().clear();
285 result.getProperties().putAll(source.getProperties());
286 }
287
288 /**
289 * Returns the message where to write results in an
290 * exchange-pattern-sensitive way.
291 *
292 * @param exchange
293 * message exchange.
294 * @return result message.
295 */
296 public static Message getResultMessage(Exchange exchange) {
297 if (exchange.getPattern().isOutCapable()) {
298 return exchange.getOut();
299 } else {
300 return exchange.getIn();
301 }
302 }
303
304 /**
305 * Returns true if the given exchange pattern (if defined) can support IN messagea
306 *
307 * @param exchange the exchange to interrogate
308 * @return true if the exchange is defined as an {@link ExchangePattern} which supports
309 * IN messages
310 */
311 public static boolean isInCapable(Exchange exchange) {
312 ExchangePattern pattern = exchange.getPattern();
313 return pattern != null && pattern.isInCapable();
314 }
315
316 /**
317 * Returns true if the given exchange pattern (if defined) can support OUT messagea
318 *
319 * @param exchange the exchange to interrogate
320 * @return true if the exchange is defined as an {@link ExchangePattern} which supports
321 * OUT messages
322 */
323 public static boolean isOutCapable(Exchange exchange) {
324 ExchangePattern pattern = exchange.getPattern();
325 return pattern != null && pattern.isOutCapable();
326 }
327
328 /**
329 * Creates a new instance of the given type from the injector
330 */
331 public static <T> T newInstance(Exchange exchange, Class<T> type) {
332 return exchange.getContext().getInjector().newInstance(type);
333 }
334
335 /**
336 * Creates a Map of the variables which are made available to a script or template
337 *
338 * @param exchange the exchange to make available
339 * @return a Map populated with the require dvariables
340 */
341 public static Map createVariableMap(Exchange exchange) {
342 Map answer = new HashMap();
343 populateVariableMap(exchange, answer);
344 return answer;
345 }
346
347 /**
348 * Populates the Map with the variables which are made available to a script or template
349 *
350 * @param exchange the exchange to make available
351 * @param map the map to populate
352 */
353 @SuppressWarnings("unchecked")
354 public static void populateVariableMap(Exchange exchange, Map map) {
355 map.put("exchange", exchange);
356 Message in = exchange.getIn();
357 map.put("in", in);
358 map.put("request", in);
359 map.put("headers", in.getHeaders());
360 map.put("body", in.getBody());
361 if (isOutCapable(exchange)) {
362 Message out = exchange.getOut(true);
363 map.put("out", out);
364 map.put("response", out);
365 }
366 map.put("camelContext", exchange.getContext());
367 }
368
369 /**
370 * Returns the MIME content type on the input message or null if one is not defined
371 */
372 public static String getContentType(Exchange exchange) {
373 return exchange.getIn().getHeader("Content-Type", String.class);
374 }
375
376 /**
377 * Performs a lookup in the registry of the mandatory bean name and throws an exception if it could not be found
378 */
379 public static Object lookupMandatoryBean(Exchange exchange, String name) {
380 Object value = lookupBean(exchange, name);
381 if (value == null) {
382 throw new NoSuchBeanException(name);
383 }
384 return value;
385 }
386
387 /**
388 * Performs a lookup in the registry of the mandatory bean name and throws an exception if it could not be found
389 */
390 public static <T> T lookupMandatoryBean(Exchange exchange, String name, Class<T> type) {
391 T value = lookupBean(exchange, name, type);
392 if (value == null) {
393 throw new NoSuchBeanException(name);
394 }
395 return value;
396 }
397
398 /**
399 * Performs a lookup in the registry of the bean name
400 */
401 public static Object lookupBean(Exchange exchange, String name) {
402 return exchange.getContext().getRegistry().lookup(name);
403 }
404
405 /**
406 * Performs a lookup in the registry of the bean name and type
407 */
408 public static <T> T lookupBean(Exchange exchange, String name, Class<T> type) {
409 return exchange.getContext().getRegistry().lookup(name, type);
410 }
411
412 /**
413 * Returns the first exchange in the given collection of exchanges which has the same exchange ID as the one given
414 * or null if none could be found
415 */
416 public static Exchange getExchangeById(Iterable<Exchange> exchanges, String exchangeId) {
417 for (Exchange exchange : exchanges) {
418 String id = exchange.getExchangeId();
419 if (id != null && id.equals(exchangeId)) {
420 return exchange;
421 }
422 }
423 return null;
424 }
425
426 public static boolean isFailureHandled(Exchange exchange) {
427 Boolean handled = exchange.getProperty(Exchange.FAILURE_HANDLED, Boolean.class);
428 return handled != null && handled;
429 }
430
431 public static void setFailureHandled(Exchange exchange) {
432 exchange.setProperty(Exchange.FAILURE_HANDLED, Boolean.TRUE);
433 // clear exception since its failure handled
434 exchange.setException(null);
435 }
436
437 }