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 */
017package org.apache.camel;
018
019import java.util.List;
020import java.util.Map;
021
022import org.apache.camel.spi.Synchronization;
023import org.apache.camel.spi.UnitOfWork;
024
025/**
026 * An Exchange is the message container holding the information during the entire routing of
027 * a {@link  Message} received by a {@link Consumer}. 
028 * <p/>
029 * During processing down the {@link Processor} chain, the {@link Exchange} provides access to the 
030 * current (not the original) request and response {@link Message} messages. The {@link Exchange} 
031 * also holds meta-data during its entire lifetime stored as properties accessible using the 
032 * various {@link #getProperty(String)} methods. The {@link #setProperty(String, Object)} is 
033 * used to store a property. For example you can use this to store security, SLA related 
034 * data or any other information deemed useful throughout processing. If an {@link Exchange} 
035 * failed during routing the {@link Exception} that caused the failure is stored and accessible 
036 * via the {@link #getException()} method.
037 * <p/>
038 * An Exchange is created when a {@link Consumer} receives a request. A new {@link Message} is
039 * created, the request is set as the body of the {@link Message} and depending on the {@link Consumer}
040 * other {@link Endpoint} and protocol related information is added as headers on the {@link Message}.
041 * Then an Exchange is created and the newly created {@link Message} is set as the in on the Exchange.
042 * Therefore an Exchange starts its life in a {@link Consumer}. The Exchange is then sent down the
043 * {@link Route} for processing along a {@link Processor} chain. The {@link Processor} as the name
044 * suggests is what processes the {@link Message} in the Exchange and Camel, in addition to 
045 * providing out-of-the-box a large number of useful processors, it also allows you to create your own. 
046 * The rule Camel uses is to take the out {@link Message} produced by the previous {@link Processor} 
047 * and set it as the in for the next {@link Processor}. If the previous {@link Processor} did not
048 * produce an out, then the in of the previous {@link Processor} is sent as the next in. At the
049 * end of the processing chain, depending on the {@link ExchangePattern Message Exchange Pattern} (or MEP)
050 * the last out (or in of no out available) is sent by the {@link Consumer} back to the original caller.
051 * <p/>
052 * Camel, in addition to providing out-of-the-box a large number of useful processors, it also allows 
053 * you to implement and use your own. When the Exchange is passed to a {@link Processor}, it always 
054 * contains an in {@link Message} and no out {@link Message}. The {@link Processor} <b>may</b> produce 
055 * an out, depending on the nature of the {@link Processor}. The in {@link Message} can be accessed 
056 * using the {@link #getIn()} method. Since the out message is null when entering the {@link Processor}, 
057 * the {@link #getOut()} method is actually a convenient factory method that will lazily instantiate a 
058 * {@link org.apache.camel.impl.DefaultMessage} which you could populate. As an alternative you could 
059 * also instantiate your specialized  {@link Message} and set it on the exchange using the 
060 * {@link #setOut(org.apache.camel.Message)} method. Please note that a {@link Message} contains not only 
061 * the body but also headers and attachments. If you are creating a new {@link Message} the headers and 
062 * attachments of the in {@link Message} are not automatically copied to the out by Camel and you'll have 
063 * to set the headers and attachments you need yourself. If your {@link Processor} is not producing a 
064 * different {@link Message} but only needs to slightly  modify the in, you can simply update the in 
065 * {@link Message} returned by {@link #getIn()}. 
066 * <p/>
067 * See this <a href="http://camel.apache.org/using-getin-or-getout-methods-on-exchange.html">FAQ entry</a> 
068 * for more details.
069 * 
070 */
071public interface Exchange {
072
073    String AUTHENTICATION                   = "CamelAuthentication";
074    String AUTHENTICATION_FAILURE_POLICY_ID = "CamelAuthenticationFailurePolicyId";
075    String ACCEPT_CONTENT_TYPE              = "CamelAcceptContentType";
076    String AGGREGATED_SIZE                  = "CamelAggregatedSize";
077    String AGGREGATED_TIMEOUT               = "CamelAggregatedTimeout";
078    String AGGREGATED_COMPLETED_BY          = "CamelAggregatedCompletedBy";
079    String AGGREGATED_CORRELATION_KEY       = "CamelAggregatedCorrelationKey";
080    String AGGREGATION_STRATEGY             = "CamelAggregationStrategy";
081    String AGGREGATION_COMPLETE_ALL_GROUPS  = "CamelAggregationCompleteAllGroups";
082    String AGGREGATION_COMPLETE_ALL_GROUPS_INCLUSIVE  = "CamelAggregationCompleteAllGroupsInclusive";
083    String ASYNC_WAIT                       = "CamelAsyncWait";
084
085    String BATCH_INDEX                = "CamelBatchIndex";
086    String BATCH_SIZE                 = "CamelBatchSize";
087    String BATCH_COMPLETE             = "CamelBatchComplete";
088    String BEAN_METHOD_NAME           = "CamelBeanMethodName";
089    String BEAN_MULTI_PARAMETER_ARRAY = "CamelBeanMultiParameterArray";
090    String BINDING                    = "CamelBinding";
091    // do not prefix with Camel and use lower-case starting letter as its a shared key
092    // used across other Apache products such as AMQ, SMX etc.
093    String BREADCRUMB_ID              = "breadcrumbId";
094
095    String CHARSET_NAME      = "CamelCharsetName";
096    String CREATED_TIMESTAMP = "CamelCreatedTimestamp";
097    String CONTENT_ENCODING  = "Content-Encoding";
098    String CONTENT_LENGTH    = "Content-Length";
099    String CONTENT_TYPE      = "Content-Type";
100    String CORRELATION_ID    = "CamelCorrelationId";
101
102    String DATASET_INDEX             = "CamelDataSetIndex";
103    String DEFAULT_CHARSET_PROPERTY  = "org.apache.camel.default.charset";
104    String DESTINATION_OVERRIDE_URL = "CamelDestinationOverrideUrl";
105    String DISABLE_HTTP_STREAM_CACHE = "CamelDisableHttpStreamCache";
106    String DUPLICATE_MESSAGE         = "CamelDuplicateMessage";
107    
108    String DOCUMENT_BUILDER_FACTORY = "CamelDocumentBuilderFactory";
109
110    String EXCEPTION_CAUGHT           = "CamelExceptionCaught";
111    String EXCEPTION_HANDLED          = "CamelExceptionHandled";
112    String EVALUATE_EXPRESSION_RESULT = "CamelEvaluateExpressionResult";
113    String ERRORHANDLER_HANDLED       = "CamelErrorHandlerHandled";
114    String EXTERNAL_REDELIVERED       = "CamelExternalRedelivered";
115
116    String FAILURE_HANDLED      = "CamelFailureHandled";
117    String FAILURE_ENDPOINT     = "CamelFailureEndpoint";
118    String FAILURE_ROUTE_ID     = "CamelFailureRouteId";
119    String FILTER_NON_XML_CHARS = "CamelFilterNonXmlChars";
120    String FILE_LOCAL_WORK_PATH = "CamelFileLocalWorkPath";
121    String FILE_NAME            = "CamelFileName";
122    String FILE_NAME_ONLY       = "CamelFileNameOnly";
123    String FILE_NAME_PRODUCED   = "CamelFileNameProduced";
124    String FILE_NAME_CONSUMED   = "CamelFileNameConsumed";
125    String FILE_PATH            = "CamelFilePath";
126    String FILE_PARENT          = "CamelFileParent";
127    String FILE_LAST_MODIFIED   = "CamelFileLastModified";
128    String FILE_LENGTH          = "CamelFileLength";
129    String FILTER_MATCHED       = "CamelFilterMatched";
130    String FILE_LOCK_FILE_ACQUIRED   = "CamelFileLockFileAcquired"; 
131    String FILE_LOCK_FILE_NAME  = "CamelFileLockFileName";
132    String FILE_LOCK_EXCLUSIVE_LOCK = "CamelFileLockExclusiveLock";
133    String FILE_LOCK_RANDOM_ACCESS_FILE = "CamelFileLockRandomAccessFile";
134
135    String GROUPED_EXCHANGE = "CamelGroupedExchange";
136    
137    String HTTP_BASE_URI           = "CamelHttpBaseUri";
138    String HTTP_CHARACTER_ENCODING = "CamelHttpCharacterEncoding";
139    String HTTP_METHOD             = "CamelHttpMethod";
140    String HTTP_PATH               = "CamelHttpPath";
141    String HTTP_PROTOCOL_VERSION   = "CamelHttpProtocolVersion";
142    String HTTP_QUERY              = "CamelHttpQuery";
143    String HTTP_RAW_QUERY          = "CamelHttpRawQuery";
144    String HTTP_RESPONSE_CODE      = "CamelHttpResponseCode";
145    String HTTP_URI                = "CamelHttpUri";
146    String HTTP_URL                = "CamelHttpUrl";
147    String HTTP_CHUNKED            = "CamelHttpChunked";
148    String HTTP_SERVLET_REQUEST    = "CamelHttpServletRequest";
149    String HTTP_SERVLET_RESPONSE   = "CamelHttpServletResponse";
150
151    String INTERCEPTED_ENDPOINT = "CamelInterceptedEndpoint";
152    String INTERCEPT_SEND_TO_ENDPOINT_WHEN_MATCHED = "CamelInterceptSendToEndpointWhenMatched";
153
154    String LANGUAGE_SCRIPT          = "CamelLanguageScript";
155    String LOG_DEBUG_BODY_MAX_CHARS = "CamelLogDebugBodyMaxChars";
156    String LOG_DEBUG_BODY_STREAMS   = "CamelLogDebugStreams";
157    String LOOP_INDEX               = "CamelLoopIndex";
158    String LOOP_SIZE                = "CamelLoopSize";
159
160    String MAXIMUM_CACHE_POOL_SIZE     = "CamelMaximumCachePoolSize";
161    String MAXIMUM_ENDPOINT_CACHE_SIZE = "CamelMaximumEndpointCacheSize";
162    String MESSAGE_HISTORY             = "CamelMessageHistory";
163    String MULTICAST_INDEX             = "CamelMulticastIndex";
164    String MULTICAST_COMPLETE          = "CamelMulticastComplete";
165
166    String NOTIFY_EVENT = "CamelNotifyEvent";
167
168    String ON_COMPLETION      = "CamelOnCompletion";
169    String OVERRULE_FILE_NAME = "CamelOverruleFileName";
170
171    String PARENT_UNIT_OF_WORK = "CamelParentUnitOfWork";
172    String STREAM_CACHE_UNIT_OF_WORK = "CamelStreamCacheUnitOfWork";
173    
174    String RECIPIENT_LIST_ENDPOINT = "CamelRecipientListEndpoint";
175    String RECEIVED_TIMESTAMP      = "CamelReceivedTimestamp";
176    String REDELIVERED             = "CamelRedelivered";
177    String REDELIVERY_COUNTER      = "CamelRedeliveryCounter";
178    String REDELIVERY_MAX_COUNTER  = "CamelRedeliveryMaxCounter";
179    String REDELIVERY_EXHAUSTED    = "CamelRedeliveryExhausted";
180    String REDELIVERY_DELAY        = "CamelRedeliveryDelay";
181    String ROLLBACK_ONLY           = "CamelRollbackOnly";
182    String ROLLBACK_ONLY_LAST      = "CamelRollbackOnlyLast";
183    String ROUTE_STOP              = "CamelRouteStop";
184    
185    String SAXPARSER_FACTORY   = "CamelSAXParserFactory";
186
187    String SOAP_ACTION        = "CamelSoapAction";
188    String SKIP_GZIP_ENCODING = "CamelSkipGzipEncoding";
189    String SKIP_WWW_FORM_URLENCODED = "CamelSkipWwwFormUrlEncoding"; 
190    String SLIP_ENDPOINT      = "CamelSlipEndpoint";
191    String SPLIT_INDEX        = "CamelSplitIndex";
192    String SPLIT_COMPLETE     = "CamelSplitComplete";
193    String SPLIT_SIZE         = "CamelSplitSize";
194
195    String TIMER_COUNTER         = "CamelTimerCounter";
196    String TIMER_FIRED_TIME      = "CamelTimerFiredTime";
197    String TIMER_NAME            = "CamelTimerName";
198    String TIMER_PERIOD          = "CamelTimerPeriod";
199    String TIMER_TIME            = "CamelTimerTime";
200    String TO_ENDPOINT           = "CamelToEndpoint";
201    String TRACE_EVENT           = "CamelTraceEvent";
202    String TRACE_EVENT_NODE_ID   = "CamelTraceEventNodeId";
203    String TRACE_EVENT_TIMESTAMP = "CamelTraceEventTimestamp";
204    String TRACE_EVENT_EXCHANGE  = "CamelTraceEventExchange";
205    String TRY_ROUTE_BLOCK       = "TryRouteBlock";
206    String TRANSFER_ENCODING     = "Transfer-Encoding";
207
208    String UNIT_OF_WORK_EXHAUSTED    = "CamelUnitOfWorkExhausted";
209    
210    /**
211     * @deprecated UNIT_OF_WORK_PROCESS_SYNC is not in use and will be removed in future Camel release
212     */
213    @Deprecated
214    String UNIT_OF_WORK_PROCESS_SYNC = "CamelUnitOfWorkProcessSync";
215
216    String XSLT_FILE_NAME   = "CamelXsltFileName";
217    String XSLT_ERROR       = "CamelXsltError";
218    String XSLT_FATAL_ERROR = "CamelXsltFatalError";
219    String XSLT_WARNING     = "CamelXsltWarning";
220
221    /**
222     * Returns the {@link ExchangePattern} (MEP) of this exchange.
223     *
224     * @return the message exchange pattern of this exchange
225     */
226    ExchangePattern getPattern();
227
228    /**
229     * Allows the {@link ExchangePattern} (MEP) of this exchange to be customized.
230     *
231     * This typically won't be required as an exchange can be created with a specific MEP
232     * by calling {@link Endpoint#createExchange(ExchangePattern)} but it is here just in case
233     * it is needed.
234     *
235     * @param pattern  the pattern 
236     */
237    void setPattern(ExchangePattern pattern);
238
239    /**
240     * Returns a property associated with this exchange by name
241     *
242     * @param name the name of the property
243     * @return the value of the given property or <tt>null</tt> if there is no property for
244     *         the given name
245     */
246    Object getProperty(String name);
247
248    /**
249     * Returns a property associated with this exchange by name
250     *
251     * @param name the name of the property
252     * @param defaultValue the default value to return if property was absent
253     * @return the value of the given property or <tt>defaultValue</tt> if there is no
254     *         property for the given name
255     */
256    Object getProperty(String name, Object defaultValue);
257
258    /**
259     * Returns a property associated with this exchange by name and specifying
260     * the type required
261     *
262     * @param name the name of the property
263     * @param type the type of the property
264     * @return the value of the given property or <tt>null</tt> if there is no property for
265     *         the given name or <tt>null</tt> if it cannot be converted to the given type
266     */
267    <T> T getProperty(String name, Class<T> type);
268
269    /**
270     * Returns a property associated with this exchange by name and specifying
271     * the type required
272     *
273     * @param name the name of the property
274     * @param defaultValue the default value to return if property was absent
275     * @param type the type of the property
276     * @return the value of the given property or <tt>defaultValue</tt> if there is no property for
277     *         the given name or <tt>null</tt> if it cannot be converted to the given type
278     */
279    <T> T getProperty(String name, Object defaultValue, Class<T> type);
280
281    /**
282     * Sets a property on the exchange
283     *
284     * @param name  of the property
285     * @param value to associate with the name
286     */
287    void setProperty(String name, Object value);
288
289    /**
290     * Removes the given property on the exchange
291     *
292     * @param name of the property
293     * @return the old value of the property
294     */
295    Object removeProperty(String name);
296
297    /**
298     * Returns all of the properties associated with the exchange
299     *
300     * @return all the headers in a Map
301     */
302    Map<String, Object> getProperties();
303
304    /**
305     * Returns whether any properties has been set
306     *
307     * @return <tt>true</tt> if any properties has been set
308     */
309    boolean hasProperties();
310
311    /**
312     * Returns the inbound request message
313     *
314     * @return the message
315     */
316    Message getIn();
317
318    /**
319     * Returns the inbound request message as the given type
320     *
321     * @param type the given type
322     * @return the message as the given type or <tt>null</tt> if not possible to covert to given type
323     */
324    <T> T getIn(Class<T> type);
325
326    /**
327     * Sets the inbound message instance
328     *
329     * @param in the inbound message
330     */
331    void setIn(Message in);
332
333    /**
334     * Returns the outbound message, lazily creating one if one has not already
335     * been associated with this exchange.
336     * <p/>
337     * <br/><b>Important:</b> If you want to change the current message, then use {@link #getIn()} instead as it will
338     * ensure headers etc. is kept and propagated when routing continues. Bottom line end users should rarely use
339     * this method.
340     * <p/>
341     * <br/>If you want to test whether an OUT message have been set or not, use the {@link #hasOut()} method.
342     * <p/>
343     * See also the class java doc for this {@link Exchange} for more details and this
344     * <a href="http://camel.apache.org/using-getin-or-getout-methods-on-exchange.html">FAQ entry</a>.
345     *
346     * @return the response
347     * @see #getIn()
348     */
349    Message getOut();
350
351    /**
352     * Returns the outbound request message as the given type
353     * <p/>
354     * <br/><b>Important:</b> If you want to change the current message, then use {@link #getIn()} instead as it will
355     * ensure headers etc. is kept and propagated when routing continues. Bottom line end users should rarely use
356     * this method.
357     * <p/>
358     * <br/>If you want to test whether an OUT message have been set or not, use the {@link #hasOut()} method.
359     * <p/>
360     * See also the class java doc for this {@link Exchange} for more details and this
361     * <a href="http://camel.apache.org/using-getin-or-getout-methods-on-exchange.html">FAQ entry</a>.
362     *
363     * @param type the given type
364     * @return the message as the given type or <tt>null</tt> if not possible to covert to given type
365     * @see #getIn(Class)
366     */
367    <T> T getOut(Class<T> type);
368
369    /**
370     * Returns whether an OUT message has been set or not.
371     *
372     * @return <tt>true</tt> if an OUT message exists, <tt>false</tt> otherwise.
373     */
374    boolean hasOut();
375
376    /**
377     * Sets the outbound message
378     *
379     * @param out the outbound message
380     */
381    void setOut(Message out);
382
383    /**
384     * Returns the exception associated with this exchange
385     *
386     * @return the exception (or null if no faults)
387     */
388    Exception getException();
389
390    /**
391     * Returns the exception associated with this exchange.
392     * <p/>
393     * Is used to get the caused exception that typically have been wrapped in some sort
394     * of Camel wrapper exception
395     * <p/>
396     * The strategy is to look in the exception hierarchy to find the first given cause that matches the type.
397     * Will start from the bottom (the real cause) and walk upwards.
398     *
399     * @param type the exception type
400     * @return the exception (or <tt>null</tt> if no caused exception matched)
401     */
402    <T> T getException(Class<T> type);
403
404    /**
405     * Sets the exception associated with this exchange
406     * <p/>
407     * Camel will wrap {@link Throwable} into {@link Exception} type to
408     * accommodate for the {@link #getException()} method returning a plain {@link Exception} type.
409     *
410     * @param t  the caused exception
411     */
412    void setException(Throwable t);
413
414    /**
415     * Returns true if this exchange failed due to either an exception or fault
416     *
417     * @return true if this exchange failed due to either an exception or fault
418     * @see Exchange#getException()
419     * @see Message#setFault(boolean)
420     * @see Message#isFault()
421     */
422    boolean isFailed();
423
424    /**
425     * Returns true if this exchange is transacted
426     */
427    boolean isTransacted();
428
429    /**
430     * Returns true if this exchange is an external initiated redelivered message (such as a JMS broker).
431     * <p/>
432     * <b>Important: </b> It is not always possible to determine if the message is a redelivery
433     * or not, and therefore <tt>null</tt> is returned. Such an example would be a JDBC message.
434     * However JMS brokers provides details if a message is redelivered.
435     *
436     * @return <tt>true</tt> if redelivered, <tt>false</tt> if not, <tt>null</tt> if not able to determine
437     */
438    Boolean isExternalRedelivered();
439
440    /**
441     * Returns true if this exchange is marked for rollback
442     */
443    boolean isRollbackOnly();
444
445    /**
446     * Returns the container so that a processor can resolve endpoints from URIs
447     *
448     * @return the container which owns this exchange
449     */
450    CamelContext getContext();
451
452    /**
453     * Creates a copy of the current message exchange so that it can be
454     * forwarded to another destination
455     */
456    Exchange copy();
457
458    /**
459     * Returns the endpoint which originated this message exchange if a consumer on an endpoint
460     * created the message exchange, otherwise this property will be <tt>null</tt>
461     */
462    Endpoint getFromEndpoint();
463
464    /**
465     * Sets the endpoint which originated this message exchange. This method
466     * should typically only be called by {@link org.apache.camel.Endpoint} implementations
467     *
468     * @param fromEndpoint the endpoint which is originating this message exchange
469     */
470    void setFromEndpoint(Endpoint fromEndpoint);
471    
472    /**
473     * Returns the route id which originated this message exchange if a route consumer on an endpoint
474     * created the message exchange, otherwise this property will be <tt>null</tt>
475     */
476    String getFromRouteId();
477
478    /**
479     * Sets the route id which originated this message exchange. This method
480     * should typically only be called by the internal framework.
481     *
482     * @param fromRouteId the from route id
483     */
484    void setFromRouteId(String fromRouteId);
485
486    /**
487     * Returns the unit of work that this exchange belongs to; which may map to
488     * zero, one or more physical transactions
489     */
490    UnitOfWork getUnitOfWork();
491
492    /**
493     * Sets the unit of work that this exchange belongs to; which may map to
494     * zero, one or more physical transactions
495     */
496    void setUnitOfWork(UnitOfWork unitOfWork);
497
498    /**
499     * Returns the exchange id (unique)
500     */
501    String getExchangeId();
502
503    /**
504     * Set the exchange id
505     */
506    void setExchangeId(String id);
507
508    /**
509     * Adds a {@link org.apache.camel.spi.Synchronization} to be invoked as callback when
510     * this exchange is completed.
511     *
512     * @param onCompletion  the callback to invoke on completion of this exchange
513     */
514    void addOnCompletion(Synchronization onCompletion);
515
516    /**
517     * Checks if the passed {@link org.apache.camel.spi.Synchronization} instance is
518     * already contained on this exchange.
519     *
520     * @param onCompletion  the callback instance that is being checked for
521     * @return <tt>true</tt>, if callback instance is already contained on this exchange, else <tt>false</tt>
522     */
523    boolean containsOnCompletion(Synchronization onCompletion);
524
525    /**
526     * Handover all the on completions from this exchange to the target exchange.
527     *
528     * @param target the target exchange
529     */
530    void handoverCompletions(Exchange target);
531
532    /**
533     * Handover all the on completions from this exchange
534     *
535     * @return the on completions
536     */
537    List<Synchronization> handoverCompletions();
538
539}