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;
018    
019    import java.util.List;
020    import java.util.Map;
021    
022    import org.apache.camel.spi.Synchronization;
023    import 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     */
071    public 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 EXCEPTION_CAUGHT           = "CamelExceptionCaught";
109        String EXCEPTION_HANDLED          = "CamelExceptionHandled";
110        String EVALUATE_EXPRESSION_RESULT = "CamelEvaluateExpressionResult";
111        String ERRORHANDLER_HANDLED       = "CamelErrorHandlerHandled";
112        String EXTERNAL_REDELIVERED       = "CamelExternalRedelivered";
113    
114        String FAILURE_HANDLED      = "CamelFailureHandled";
115        String FAILURE_ENDPOINT     = "CamelFailureEndpoint";
116        String FAILURE_ROUTE_ID     = "CamelFailureRouteId";
117        String FILTER_NON_XML_CHARS = "CamelFilterNonXmlChars";
118        String FILE_LOCAL_WORK_PATH = "CamelFileLocalWorkPath";
119        String FILE_NAME            = "CamelFileName";
120        String FILE_NAME_ONLY       = "CamelFileNameOnly";
121        String FILE_NAME_PRODUCED   = "CamelFileNameProduced";
122        String FILE_NAME_CONSUMED   = "CamelFileNameConsumed";
123        String FILE_PATH            = "CamelFilePath";
124        String FILE_PARENT          = "CamelFileParent";
125        String FILE_LAST_MODIFIED   = "CamelFileLastModified";
126        String FILE_LENGTH          = "CamelFileLength";
127        String FILTER_MATCHED       = "CamelFilterMatched";
128        String FILE_LOCK_FILE_ACQUIRED   = "CamelFileLockFileAcquired"; 
129        String FILE_LOCK_FILE_NAME  = "CamelFileLockFileName";
130    
131        String GROUPED_EXCHANGE = "CamelGroupedExchange";
132        
133        String HTTP_BASE_URI           = "CamelHttpBaseUri";
134        String HTTP_CHARACTER_ENCODING = "CamelHttpCharacterEncoding";
135        String HTTP_METHOD             = "CamelHttpMethod";
136        String HTTP_PATH               = "CamelHttpPath";
137        String HTTP_PROTOCOL_VERSION   = "CamelHttpProtocolVersion";
138        String HTTP_QUERY              = "CamelHttpQuery";
139        String HTTP_RAW_QUERY          = "CamelHttpRawQuery";
140        String HTTP_RESPONSE_CODE      = "CamelHttpResponseCode";
141        String HTTP_URI                = "CamelHttpUri";
142        String HTTP_URL                = "CamelHttpUrl";
143        String HTTP_CHUNKED            = "CamelHttpChunked";
144        String HTTP_SERVLET_REQUEST    = "CamelHttpServletRequest";
145        String HTTP_SERVLET_RESPONSE   = "CamelHttpServletResponse";
146    
147        String INTERCEPTED_ENDPOINT = "CamelInterceptedEndpoint";
148        String INTERCEPT_SEND_TO_ENDPOINT_WHEN_MATCHED = "CamelInterceptSendToEndpointWhenMatched";
149    
150        String LANGUAGE_SCRIPT          = "CamelLanguageScript";
151        String LOG_DEBUG_BODY_MAX_CHARS = "CamelLogDebugBodyMaxChars";
152        String LOG_DEBUG_BODY_STREAMS   = "CamelLogDebugStreams";
153        String LOOP_INDEX               = "CamelLoopIndex";
154        String LOOP_SIZE                = "CamelLoopSize";
155    
156        String MAXIMUM_CACHE_POOL_SIZE     = "CamelMaximumCachePoolSize";
157        String MAXIMUM_ENDPOINT_CACHE_SIZE = "CamelMaximumEndpointCacheSize";
158        String MESSAGE_HISTORY             = "CamelMessageHistory";
159        String MULTICAST_INDEX             = "CamelMulticastIndex";
160        String MULTICAST_COMPLETE          = "CamelMulticastComplete";
161    
162        String NOTIFY_EVENT = "CamelNotifyEvent";
163    
164        String ON_COMPLETION      = "CamelOnCompletion";
165        String OVERRULE_FILE_NAME = "CamelOverruleFileName";
166    
167        String PARENT_UNIT_OF_WORK = "CamelParentUnitOfWork";
168    
169        String RECIPIENT_LIST_ENDPOINT = "CamelRecipientListEndpoint";
170        String RECEIVED_TIMESTAMP      = "CamelReceivedTimestamp";
171        String REDELIVERED             = "CamelRedelivered";
172        String REDELIVERY_COUNTER      = "CamelRedeliveryCounter";
173        String REDELIVERY_MAX_COUNTER  = "CamelRedeliveryMaxCounter";
174        String REDELIVERY_EXHAUSTED    = "CamelRedeliveryExhausted";
175        String REDELIVERY_DELAY        = "CamelRedeliveryDelay";
176        String ROLLBACK_ONLY           = "CamelRollbackOnly";
177        String ROLLBACK_ONLY_LAST      = "CamelRollbackOnlyLast";
178        String ROUTE_STOP              = "CamelRouteStop";
179    
180        String SOAP_ACTION        = "CamelSoapAction";
181        String SKIP_GZIP_ENCODING = "CamelSkipGzipEncoding";
182        String SKIP_WWW_FORM_URLENCODED = "CamelSkipWwwFormUrlEncoding"; 
183        String SLIP_ENDPOINT      = "CamelSlipEndpoint";
184        String SPLIT_INDEX        = "CamelSplitIndex";
185        String SPLIT_COMPLETE     = "CamelSplitComplete";
186        String SPLIT_SIZE         = "CamelSplitSize";
187    
188        String TIMER_COUNTER         = "CamelTimerCounter";
189        String TIMER_FIRED_TIME      = "CamelTimerFiredTime";
190        String TIMER_NAME            = "CamelTimerName";
191        String TIMER_PERIOD          = "CamelTimerPeriod";
192        String TIMER_TIME            = "CamelTimerTime";
193        String TO_ENDPOINT           = "CamelToEndpoint";
194        String TRACE_EVENT           = "CamelTraceEvent";
195        String TRACE_EVENT_NODE_ID   = "CamelTraceEventNodeId";
196        String TRACE_EVENT_TIMESTAMP = "CamelTraceEventTimestamp";
197        String TRACE_EVENT_EXCHANGE  = "CamelTraceEventExchange";
198        String TRY_ROUTE_BLOCK       = "TryRouteBlock";
199        String TRANSFER_ENCODING     = "Transfer-Encoding";
200    
201        String UNIT_OF_WORK_EXHAUSTED    = "CamelUnitOfWorkExhausted";
202        /**
203         * @deprecated UNIT_OF_WORK_PROCESS_SYNC is not in use and will be removed in future Camel release
204         */
205        @Deprecated
206        String UNIT_OF_WORK_PROCESS_SYNC = "CamelUnitOfWorkProcessSync";
207    
208        String XSLT_FILE_NAME = "CamelXsltFileName";
209    
210        /**
211         * Returns the {@link ExchangePattern} (MEP) of this exchange.
212         *
213         * @return the message exchange pattern of this exchange
214         */
215        ExchangePattern getPattern();
216    
217        /**
218         * Allows the {@link ExchangePattern} (MEP) of this exchange to be customized.
219         *
220         * This typically won't be required as an exchange can be created with a specific MEP
221         * by calling {@link Endpoint#createExchange(ExchangePattern)} but it is here just in case
222         * it is needed.
223         *
224         * @param pattern  the pattern 
225         */
226        void setPattern(ExchangePattern pattern);
227    
228        /**
229         * Returns a property associated with this exchange by name
230         *
231         * @param name the name of the property
232         * @return the value of the given property or <tt>null</tt> if there is no property for
233         *         the given name
234         */
235        Object getProperty(String name);
236    
237        /**
238         * Returns a property associated with this exchange by name
239         *
240         * @param name the name of the property
241         * @param defaultValue the default value to return if property was absent
242         * @return the value of the given property or <tt>defaultValue</tt> if there is no
243         *         property for the given name
244         */
245        Object getProperty(String name, Object defaultValue);
246    
247        /**
248         * Returns a property associated with this exchange by name and specifying
249         * the type required
250         *
251         * @param name the name of the property
252         * @param type the type of the property
253         * @return the value of the given property or <tt>null</tt> if there is no property for
254         *         the given name or <tt>null</tt> if it cannot be converted to the given type
255         */
256        <T> T getProperty(String name, Class<T> type);
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 defaultValue the default value to return if property was absent
264         * @param type the type of the property
265         * @return the value of the given property or <tt>defaultValue</tt> if there is no property for
266         *         the given name or <tt>null</tt> if it cannot be converted to the given type
267         */
268        <T> T getProperty(String name, Object defaultValue, Class<T> type);
269    
270        /**
271         * Sets a property on the exchange
272         *
273         * @param name  of the property
274         * @param value to associate with the name
275         */
276        void setProperty(String name, Object value);
277    
278        /**
279         * Removes the given property on the exchange
280         *
281         * @param name of the property
282         * @return the old value of the property
283         */
284        Object removeProperty(String name);
285    
286        /**
287         * Returns all of the properties associated with the exchange
288         *
289         * @return all the headers in a Map
290         */
291        Map<String, Object> getProperties();
292    
293        /**
294         * Returns whether any properties has been set
295         *
296         * @return <tt>true</tt> if any properties has been set
297         */
298        boolean hasProperties();
299    
300        /**
301         * Returns the inbound request message
302         *
303         * @return the message
304         */
305        Message getIn();
306    
307        /**
308         * Returns the inbound request message as the given type
309         *
310         * @param type the given type
311         * @return the message as the given type or <tt>null</tt> if not possible to covert to given type
312         */
313        <T> T getIn(Class<T> type);
314    
315        /**
316         * Sets the inbound message instance
317         *
318         * @param in the inbound message
319         */
320        void setIn(Message in);
321    
322        /**
323         * Returns the outbound message, lazily creating one if one has not already
324         * been associated with this exchange.
325         * <p/>
326         * <br/><b>Important:</b> If you want to change the current message, then use {@link #getIn()} instead as it will
327         * ensure headers etc. is kept and propagated when routing continues. Bottom line end users should rarely use
328         * this method.
329         * <p/>
330         * <br/>If you want to test whether an OUT message have been set or not, use the {@link #hasOut()} method.
331         * <p/>
332         * See also the class java doc for this {@link Exchange} for more details and this
333         * <a href="http://camel.apache.org/using-getin-or-getout-methods-on-exchange.html">FAQ entry</a>.
334         *
335         * @return the response
336         * @see #getIn()
337         */
338        Message getOut();
339    
340        /**
341         * Returns the outbound request message as the given type
342         * <p/>
343         * <br/><b>Important:</b> If you want to change the current message, then use {@link #getIn()} instead as it will
344         * ensure headers etc. is kept and propagated when routing continues. Bottom line end users should rarely use
345         * this method.
346         * <p/>
347         * <br/>If you want to test whether an OUT message have been set or not, use the {@link #hasOut()} method.
348         * <p/>
349         * See also the class java doc for this {@link Exchange} for more details and this
350         * <a href="http://camel.apache.org/using-getin-or-getout-methods-on-exchange.html">FAQ entry</a>.
351         *
352         * @param type the given type
353         * @return the message as the given type or <tt>null</tt> if not possible to covert to given type
354         * @see #getIn(Class)
355         */
356        <T> T getOut(Class<T> type);
357    
358        /**
359         * Returns whether an OUT message has been set or not.
360         *
361         * @return <tt>true</tt> if an OUT message exists, <tt>false</tt> otherwise.
362         */
363        boolean hasOut();
364    
365        /**
366         * Sets the outbound message
367         *
368         * @param out the outbound message
369         */
370        void setOut(Message out);
371    
372        /**
373         * Returns the exception associated with this exchange
374         *
375         * @return the exception (or null if no faults)
376         */
377        Exception getException();
378    
379        /**
380         * Returns the exception associated with this exchange.
381         * <p/>
382         * Is used to get the caused exception that typically have been wrapped in some sort
383         * of Camel wrapper exception
384         * <p/>
385         * The strategy is to look in the exception hierarchy to find the first given cause that matches the type.
386         * Will start from the bottom (the real cause) and walk upwards.
387         *
388         * @param type the exception type
389         * @return the exception (or <tt>null</tt> if no caused exception matched)
390         */
391        <T> T getException(Class<T> type);
392    
393        /**
394         * Sets the exception associated with this exchange
395         * <p/>
396         * Camel will wrap {@link Throwable} into {@link Exception} type to
397         * accommodate for the {@link #getException()} method returning a plain {@link Exception} type.
398         *
399         * @param t  the caused exception
400         */
401        void setException(Throwable t);
402    
403        /**
404         * Returns true if this exchange failed due to either an exception or fault
405         *
406         * @return true if this exchange failed due to either an exception or fault
407         * @see Exchange#getException()
408         * @see Message#setFault(boolean)
409         * @see Message#isFault()
410         */
411        boolean isFailed();
412    
413        /**
414         * Returns true if this exchange is transacted
415         */
416        boolean isTransacted();
417    
418        /**
419         * Returns true if this exchange is an external initiated redelivered message (such as a JMS broker).
420         * <p/>
421         * <b>Important: </b> It is not always possible to determine if the message is a redelivery
422         * or not, and therefore <tt>null</tt> is returned. Such an example would be a JDBC message.
423         * However JMS brokers provides details if a message is redelivered.
424         *
425         * @return <tt>true</tt> if redelivered, <tt>false</tt> if not, <tt>null</tt> if not able to determine
426         */
427        Boolean isExternalRedelivered();
428    
429        /**
430         * Returns true if this exchange is marked for rollback
431         */
432        boolean isRollbackOnly();
433    
434        /**
435         * Returns the container so that a processor can resolve endpoints from URIs
436         *
437         * @return the container which owns this exchange
438         */
439        CamelContext getContext();
440    
441        /**
442         * Creates a copy of the current message exchange so that it can be
443         * forwarded to another destination
444         */
445        Exchange copy();
446    
447        /**
448         * Returns the endpoint which originated this message exchange if a consumer on an endpoint
449         * created the message exchange, otherwise this property will be <tt>null</tt>
450         */
451        Endpoint getFromEndpoint();
452    
453        /**
454         * Sets the endpoint which originated this message exchange. This method
455         * should typically only be called by {@link org.apache.camel.Endpoint} implementations
456         *
457         * @param fromEndpoint the endpoint which is originating this message exchange
458         */
459        void setFromEndpoint(Endpoint fromEndpoint);
460        
461        /**
462         * Returns the route id which originated this message exchange if a route consumer on an endpoint
463         * created the message exchange, otherwise this property will be <tt>null</tt>
464         */
465        String getFromRouteId();
466    
467        /**
468         * Sets the route id which originated this message exchange. This method
469         * should typically only be called by the internal framework.
470         *
471         * @param fromRouteId the from route id
472         */
473        void setFromRouteId(String fromRouteId);
474    
475        /**
476         * Returns the unit of work that this exchange belongs to; which may map to
477         * zero, one or more physical transactions
478         */
479        UnitOfWork getUnitOfWork();
480    
481        /**
482         * Sets the unit of work that this exchange belongs to; which may map to
483         * zero, one or more physical transactions
484         */
485        void setUnitOfWork(UnitOfWork unitOfWork);
486    
487        /**
488         * Returns the exchange id (unique)
489         */
490        String getExchangeId();
491    
492        /**
493         * Set the exchange id
494         */
495        void setExchangeId(String id);
496    
497        /**
498         * Adds a {@link org.apache.camel.spi.Synchronization} to be invoked as callback when
499         * this exchange is completed.
500         *
501         * @param onCompletion  the callback to invoke on completion of this exchange
502         */
503        void addOnCompletion(Synchronization onCompletion);
504    
505        /**
506         * Checks if the passed {@link org.apache.camel.spi.Synchronization} instance is
507         * already contained on this exchange.
508         *
509         * @param onCompletion  the callback instance that is being checked for
510         * @return <tt>true</tt>, if callback instance is already contained on this exchange, else <tt>false</tt>
511         */
512        boolean containsOnCompletion(Synchronization onCompletion);
513    
514        /**
515         * Handover all the on completions from this exchange to the target exchange.
516         *
517         * @param target the target exchange
518         */
519        void handoverCompletions(Exchange target);
520    
521        /**
522         * Handover all the on completions from this exchange
523         *
524         * @return the on completions
525         */
526        List<Synchronization> handoverCompletions();
527    
528    }