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 }