This is an automated email from the ASF dual-hosted git repository.

orpiske pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 72c146dc9ea26c11744d8a408d14c1096425fcef
Author: Otavio Rodolfo Piske <angusyo...@gmail.com>
AuthorDate: Mon Feb 13 17:04:57 2023 +0100

    CAMEL-15105: decouple the ExtendedExchange from the Exchange
---
 .../src/main/java/org/apache/camel/Exchange.java   |   4 +
 ...xtendedExchange.java => ExchangeExtension.java} | 179 ++++++++---------
 .../java/org/apache/camel/ExtendedExchange.java    | 220 +--------------------
 .../java/org/apache/camel/SafeCopyProperty.java    |   4 +-
 .../org/apache/camel/support/AbstractExchange.java |  22 ++-
 .../camel/support/ExtendedExchangeExtension.java   | 216 ++++++++++++++++++++
 6 files changed, 333 insertions(+), 312 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/Exchange.java 
b/core/camel-api/src/main/java/org/apache/camel/Exchange.java
index 7e248c0e578..1ad47031e7b 100644
--- a/core/camel-api/src/main/java/org/apache/camel/Exchange.java
+++ b/core/camel-api/src/main/java/org/apache/camel/Exchange.java
@@ -270,6 +270,8 @@ public interface Exchange {
      * <p/>
      * For example to adapt to <tt>ExtendedExchange</tt>.
      *
+     * This method is deprecated. Use the getter to {@link ExchangeExtension}.
+     *
      * @param  type the type to adapt to
      * @return      this {@link org.apache.camel.Exchange} adapted to the 
given type
      */
@@ -680,4 +682,6 @@ public interface Exchange {
      */
     long getCreated();
 
+    ExchangeExtension getExchangeExtension();
+
 }
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/ExtendedExchange.java 
b/core/camel-api/src/main/java/org/apache/camel/ExchangeExtension.java
similarity index 92%
copy from core/camel-api/src/main/java/org/apache/camel/ExtendedExchange.java
copy to core/camel-api/src/main/java/org/apache/camel/ExchangeExtension.java
index 929b7c0a943..999ad17979d 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExtendedExchange.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExchangeExtension.java
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.camel;
 
 import java.util.List;
@@ -22,17 +23,17 @@ import java.util.Map;
 import org.apache.camel.spi.Synchronization;
 import org.apache.camel.spi.UnitOfWork;
 
-/**
- * Extended {@link Exchange} which contains the methods and APIs that are not 
intended for Camel end users but used
- * internally by Camel for optimization purposes, SPI, custom components, or 
more advanced used-cases with Camel.
+/*
+ * {@link Exchange} extensions which contains the methods and APIs that are 
not intended for Camel end users but
+ * used internally by Camel for optimization purposes, SPI, custom components, 
or more advanced used-cases with
+ * Camel.
  */
-public interface ExtendedExchange extends Exchange {
-
+public interface ExchangeExtension {
     /**
      * If there is an existing inbound message of the given type then return 
it as-is, otherwise return null.
      *
-     * @param  type the given type
-     * @return      the message if exists with the given type, otherwise null.
+     * @param type the given type
+     * @return the message if exists with the given type, otherwise null.
      */
     <T> T getInOrNull(Class<T> type);
 
@@ -54,9 +55,14 @@ public interface ExtendedExchange extends Exchange {
     void setUnitOfWork(UnitOfWork unitOfWork);
 
     /**
-     * Sets the properties on the exchange
+     * Is stream caching disabled on the given exchange
      */
-    void setProperties(Map<String, Object> properties);
+    boolean isStreamCacheDisabled();
+
+    /**
+     * Used to force disabling stream caching which some components can do in 
special use-cases.
+     */
+    void setStreamCacheDisabled(boolean streamCacheDisabled);
 
     /**
      * Adds a {@link org.apache.camel.spi.Synchronization} to be invoked as 
callback when this exchange is completed.
@@ -66,141 +72,145 @@ public interface ExtendedExchange extends Exchange {
     void addOnCompletion(Synchronization onCompletion);
 
     /**
-     * Checks if the passed {@link Synchronization} instance is already 
contained on this exchange.
-     *
-     * @param  onCompletion the callback instance that is being checked for
-     * @return              <tt>true</tt>, if callback instance is already 
contained on this exchange, else
-     *                      <tt>false</tt>
+     * Whether the error handler handled flag has been set.
      */
-    boolean containsOnCompletion(Synchronization onCompletion);
+    boolean isErrorHandlerHandledSet();
 
     /**
-     * Handover all the on completions from this exchange to the target 
exchange.
+     * Whether the exchange has been handled by the error handler. This is 
used internally by Camel.
+     * <p>
+     * Important: Call {@link #isErrorHandlerHandledSet()} first before this 
method.
+     *
+     * @see #isErrorHandlerHandledSet()
      */
-    void handoverCompletions(Exchange target);
+    boolean isErrorHandlerHandled();
 
     /**
-     * Handover all the on completions from this exchange
+     * Whether the exchange has been handled by the error handler. This is 
used internally by Camel.
      */
-    List<Synchronization> handoverCompletions();
+    Boolean getErrorHandlerHandled();
 
     /**
-     * Sets the history node id (the current processor that will process the 
exchange)
+     * Used to signal that this exchange has been handled by the error 
handler. This is used internally by Camel.
      */
-    void setHistoryNodeId(String historyNodeId);
+    void setErrorHandlerHandled(Boolean errorHandlerHandled);
 
     /**
-     * Gets the history node id (the current processor that will process the 
exchange)
+     * To control whether the exchange can accept being interrupted currently.
      */
-    String getHistoryNodeId();
+    void setInterruptable(boolean interruptable);
 
     /**
-     * Sets the history node label (the current processor that will process 
the exchange)
+     * Whether the exchange was interrupted (InterruptException) during 
routing.
      */
-    void setHistoryNodeLabel(String historyNodeLabel);
+    boolean isInterrupted();
 
     /**
-     * Gets the history node label (the current processor that will process 
the exchange)
+     * Used to signal that this exchange was interrupted (InterruptException) 
during routing.
      */
-    String getHistoryNodeLabel();
+    void setInterrupted(boolean interrupted);
 
     /**
-     * Gets the history node source:line-number where the node is located in 
the source code (the current processor that
-     * will process the exchange).
+     * Whether the exchange has exhausted (attempted all) its redeliveries and 
still failed. This is used internally by
+     * Camel.
      */
-    String getHistoryNodeSource();
+    boolean isRedeliveryExhausted();
 
     /**
-     * Sets the history node source:line-number where the node is located in 
the source code (the current processor that
-     * will process the exchange).
+     * Used to signal that this exchange has exhausted (attempted all) its 
redeliveries and still failed. This is used
+     * internally by Camel.
      */
-    void setHistoryNodeSource(String historyNodeSource);
+    void setRedeliveryExhausted(boolean redeliveryExhausted);
 
     /**
-     * Is stream caching disabled on the given exchange
+     * Checks if the passed {@link Synchronization} instance is already 
contained on this exchange.
+     *
+     * @param onCompletion the callback instance that is being checked for
+     * @return <tt>true</tt>, if callback instance is already contained on 
this exchange, else
+     * <tt>false</tt>
      */
-    boolean isStreamCacheDisabled();
+    boolean containsOnCompletion(Synchronization onCompletion);
 
     /**
-     * Used to force disabling stream caching which some components can do in 
special use-cases.
+     * Handover all the on completions from this exchange to the target 
exchange.
      */
-    void setStreamCacheDisabled(boolean streamCacheDisabled);
+    void handoverCompletions(Exchange target);
 
     /**
-     * Sets whether the exchange is routed in a transaction.
+     * Handover all the on completions from this exchange
      */
-    void setTransacted(boolean transacted);
+    List<Synchronization> handoverCompletions();
 
     /**
-     * Whether the exchange is currently used as event notification.
+     * Sets the properties on the exchange
      */
-    boolean isNotifyEvent();
+    void setProperties(Map<String, Object> properties);
 
     /**
-     * Sets whether the exchange is currently used as event notification and 
if so then this should not generate
-     * additional events.
+     * Sets the history node id (the current processor that will process the 
exchange)
      */
-    void setNotifyEvent(boolean notifyEvent);
+    void setHistoryNodeId(String historyNodeId);
 
     /**
-     * Whether the exchange was interrupted (InterruptException) during 
routing.
+     * Gets the history node id (the current processor that will process the 
exchange)
      */
-    boolean isInterrupted();
+    String getHistoryNodeId();
 
     /**
-     * Used to signal that this exchange was interrupted (InterruptException) 
during routing.
+     * Gets the history node source:line-number where the node is located in 
the source code (the current processor that
+     * will process the exchange).
      */
-    void setInterrupted(boolean interrupted);
+    String getHistoryNodeSource();
 
     /**
-     * To control whether the exchange can accept being interrupted currently.
+     * Sets the history node source:line-number where the node is located in 
the source code (the current processor that
+     * will process the exchange).
      */
-    void setInterruptable(boolean interruptable);
+    void setHistoryNodeSource(String historyNodeSource);
 
     /**
-     * Whether the exchange has exhausted (attempted all) its redeliveries and 
still failed. This is used internally by
-     * Camel.
+     * Gets the history node label (the current processor that will process 
the exchange)
      */
-    boolean isRedeliveryExhausted();
+    String getHistoryNodeLabel();
 
     /**
-     * Used to signal that this exchange has exhausted (attempted all) its 
redeliveries and still failed. This is used
-     * internally by Camel.
+     * Sets the history node label (the current processor that will process 
the exchange)
      */
-    void setRedeliveryExhausted(boolean redeliveryExhausted);
+    void setHistoryNodeLabel(String historyNodeLabel);
 
     /**
-     * Whether the exchange has been handled by the error handler. This is 
used internally by Camel.
-     *
-     * Important: Call {@link #isErrorHandlerHandledSet()} first before this 
method.
-     *
-     * @see #isErrorHandlerHandledSet()
+     * Whether the exchange is currently used as event notification.
      */
-    boolean isErrorHandlerHandled();
+    boolean isNotifyEvent();
 
     /**
-     * Whether the error handler handled flag has been set.
+     * Sets whether the exchange is currently used as event notification and 
if so then this should not generate
+     * additional events.
      */
-    boolean isErrorHandlerHandledSet();
+    void setNotifyEvent(boolean notifyEvent);
 
     /**
-     * Whether the exchange has been handled by the error handler. This is 
used internally by Camel.
+     * To copy the internal properties from this exchange to the target 
exchange
+     * <p/>
+     * This method is only intended for Camel internally.
+     *
+     * @param target the target exchange
      */
-    Boolean getErrorHandlerHandled();
+    void copyInternalProperties(Exchange target);
 
     /**
-     * Used to signal that this exchange has been handled by the error 
handler. This is used internally by Camel.
+     * To get a property that was copied specially (thread safe with deep 
cloning).
+     *
+     * @see SafeCopyProperty
      */
-    void setErrorHandlerHandled(Boolean errorHandlerHandled);
+    <T> T getSafeCopyProperty(String key, Class<T> type);
 
     /**
-     * To copy the internal properties from this exchange to the target 
exchange
-     * <p/>
-     * This method is only intended for Camel internally.
+     * To set a property that must be copied specially (thread safe with deep 
cloning).
      *
-     * @param target the target exchange
+     * @see SafeCopyProperty
      */
-    void copyInternalProperties(Exchange target);
+    void setSafeCopyProperty(String key, SafeCopyProperty value);
 
     /**
      * Gets the internal properties from this exchange. The known set of 
internal keys is defined in
@@ -212,31 +222,22 @@ public interface ExtendedExchange extends Exchange {
      */
     Map<String, Object> getInternalProperties();
 
+    /**
+     * Sets whether the exchange is routed in a transaction.
+     */
+    void setTransacted(boolean transacted);
+
     /**
      * Callback used by {@link Consumer} if the consumer is completing the 
exchange processing with default behaviour.
-     *
+     * <p>
      * This is only used when pooled exchange is enabled for optimization and 
reducing object allocations.
      */
     AsyncCallback getDefaultConsumerCallback();
 
     /**
      * Callback used by {@link Consumer} if the consumer is completing the 
exchange processing with default behaviour.
-     *
+     * <p>
      * This is only used when pooled exchange is enabled for optimization and 
reducing object allocations.
      */
     void setDefaultConsumerCallback(AsyncCallback callback);
-
-    /**
-     * To set a property that must be copied specially (thread safe with deep 
cloning).
-     *
-     * @see SafeCopyProperty
-     */
-    void setSafeCopyProperty(String key, SafeCopyProperty value);
-
-    /**
-     * To get a property that was copied specially (thread safe with deep 
cloning).
-     *
-     * @see SafeCopyProperty
-     */
-    <T> T getSafeCopyProperty(String key, Class<T> type);
 }
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/ExtendedExchange.java 
b/core/camel-api/src/main/java/org/apache/camel/ExtendedExchange.java
index 929b7c0a943..0c89ca439a8 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExtendedExchange.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedExchange.java
@@ -16,227 +16,13 @@
  */
 package org.apache.camel;
 
-import java.util.List;
-import java.util.Map;
-
-import org.apache.camel.spi.Synchronization;
-import org.apache.camel.spi.UnitOfWork;
-
 /**
  * Extended {@link Exchange} which contains the methods and APIs that are not 
intended for Camel end users but used
  * internally by Camel for optimization purposes, SPI, custom components, or 
more advanced used-cases with Camel.
+ *
+ * This interface is deprecated. Use {@link ExchangeExtension}
  */
+@Deprecated
 public interface ExtendedExchange extends Exchange {
 
-    /**
-     * If there is an existing inbound message of the given type then return 
it as-is, otherwise return null.
-     *
-     * @param  type the given type
-     * @return      the message if exists with the given type, otherwise null.
-     */
-    <T> T getInOrNull(Class<T> type);
-
-    /**
-     * Sets the endpoint which originated this message exchange. This method 
should typically only be called by
-     * {@link Endpoint} implementations
-     */
-    void setFromEndpoint(Endpoint fromEndpoint);
-
-    /**
-     * Sets the route id which originated this message exchange. This method 
should typically only be called by the
-     * internal framework.
-     */
-    void setFromRouteId(String fromRouteId);
-
-    /**
-     * Sets the unit of work that this exchange belongs to; which may map to 
zero, one or more physical transactions
-     */
-    void setUnitOfWork(UnitOfWork unitOfWork);
-
-    /**
-     * Sets the properties on the exchange
-     */
-    void setProperties(Map<String, Object> properties);
-
-    /**
-     * Adds a {@link org.apache.camel.spi.Synchronization} to be invoked as 
callback when this exchange is completed.
-     *
-     * @param onCompletion the callback to invoke on completion of this 
exchange
-     */
-    void addOnCompletion(Synchronization onCompletion);
-
-    /**
-     * Checks if the passed {@link Synchronization} instance is already 
contained on this exchange.
-     *
-     * @param  onCompletion the callback instance that is being checked for
-     * @return              <tt>true</tt>, if callback instance is already 
contained on this exchange, else
-     *                      <tt>false</tt>
-     */
-    boolean containsOnCompletion(Synchronization onCompletion);
-
-    /**
-     * Handover all the on completions from this exchange to the target 
exchange.
-     */
-    void handoverCompletions(Exchange target);
-
-    /**
-     * Handover all the on completions from this exchange
-     */
-    List<Synchronization> handoverCompletions();
-
-    /**
-     * Sets the history node id (the current processor that will process the 
exchange)
-     */
-    void setHistoryNodeId(String historyNodeId);
-
-    /**
-     * Gets the history node id (the current processor that will process the 
exchange)
-     */
-    String getHistoryNodeId();
-
-    /**
-     * Sets the history node label (the current processor that will process 
the exchange)
-     */
-    void setHistoryNodeLabel(String historyNodeLabel);
-
-    /**
-     * Gets the history node label (the current processor that will process 
the exchange)
-     */
-    String getHistoryNodeLabel();
-
-    /**
-     * Gets the history node source:line-number where the node is located in 
the source code (the current processor that
-     * will process the exchange).
-     */
-    String getHistoryNodeSource();
-
-    /**
-     * Sets the history node source:line-number where the node is located in 
the source code (the current processor that
-     * will process the exchange).
-     */
-    void setHistoryNodeSource(String historyNodeSource);
-
-    /**
-     * Is stream caching disabled on the given exchange
-     */
-    boolean isStreamCacheDisabled();
-
-    /**
-     * Used to force disabling stream caching which some components can do in 
special use-cases.
-     */
-    void setStreamCacheDisabled(boolean streamCacheDisabled);
-
-    /**
-     * Sets whether the exchange is routed in a transaction.
-     */
-    void setTransacted(boolean transacted);
-
-    /**
-     * Whether the exchange is currently used as event notification.
-     */
-    boolean isNotifyEvent();
-
-    /**
-     * Sets whether the exchange is currently used as event notification and 
if so then this should not generate
-     * additional events.
-     */
-    void setNotifyEvent(boolean notifyEvent);
-
-    /**
-     * Whether the exchange was interrupted (InterruptException) during 
routing.
-     */
-    boolean isInterrupted();
-
-    /**
-     * Used to signal that this exchange was interrupted (InterruptException) 
during routing.
-     */
-    void setInterrupted(boolean interrupted);
-
-    /**
-     * To control whether the exchange can accept being interrupted currently.
-     */
-    void setInterruptable(boolean interruptable);
-
-    /**
-     * Whether the exchange has exhausted (attempted all) its redeliveries and 
still failed. This is used internally by
-     * Camel.
-     */
-    boolean isRedeliveryExhausted();
-
-    /**
-     * Used to signal that this exchange has exhausted (attempted all) its 
redeliveries and still failed. This is used
-     * internally by Camel.
-     */
-    void setRedeliveryExhausted(boolean redeliveryExhausted);
-
-    /**
-     * Whether the exchange has been handled by the error handler. This is 
used internally by Camel.
-     *
-     * Important: Call {@link #isErrorHandlerHandledSet()} first before this 
method.
-     *
-     * @see #isErrorHandlerHandledSet()
-     */
-    boolean isErrorHandlerHandled();
-
-    /**
-     * Whether the error handler handled flag has been set.
-     */
-    boolean isErrorHandlerHandledSet();
-
-    /**
-     * Whether the exchange has been handled by the error handler. This is 
used internally by Camel.
-     */
-    Boolean getErrorHandlerHandled();
-
-    /**
-     * Used to signal that this exchange has been handled by the error 
handler. This is used internally by Camel.
-     */
-    void setErrorHandlerHandled(Boolean errorHandlerHandled);
-
-    /**
-     * To copy the internal properties from this exchange to the target 
exchange
-     * <p/>
-     * This method is only intended for Camel internally.
-     *
-     * @param target the target exchange
-     */
-    void copyInternalProperties(Exchange target);
-
-    /**
-     * Gets the internal properties from this exchange. The known set of 
internal keys is defined in
-     * {@link ExchangePropertyKey}.
-     * <p/>
-     * This method is only intended for Camel internally.
-     *
-     * @return all the internal properties in a Map
-     */
-    Map<String, Object> getInternalProperties();
-
-    /**
-     * Callback used by {@link Consumer} if the consumer is completing the 
exchange processing with default behaviour.
-     *
-     * This is only used when pooled exchange is enabled for optimization and 
reducing object allocations.
-     */
-    AsyncCallback getDefaultConsumerCallback();
-
-    /**
-     * Callback used by {@link Consumer} if the consumer is completing the 
exchange processing with default behaviour.
-     *
-     * This is only used when pooled exchange is enabled for optimization and 
reducing object allocations.
-     */
-    void setDefaultConsumerCallback(AsyncCallback callback);
-
-    /**
-     * To set a property that must be copied specially (thread safe with deep 
cloning).
-     *
-     * @see SafeCopyProperty
-     */
-    void setSafeCopyProperty(String key, SafeCopyProperty value);
-
-    /**
-     * To get a property that was copied specially (thread safe with deep 
cloning).
-     *
-     * @see SafeCopyProperty
-     */
-    <T> T getSafeCopyProperty(String key, Class<T> type);
 }
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/SafeCopyProperty.java 
b/core/camel-api/src/main/java/org/apache/camel/SafeCopyProperty.java
index 4c35f6abd8b..48abbdc2afb 100644
--- a/core/camel-api/src/main/java/org/apache/camel/SafeCopyProperty.java
+++ b/core/camel-api/src/main/java/org/apache/camel/SafeCopyProperty.java
@@ -19,10 +19,10 @@ package org.apache.camel;
 /**
  * An interface that allows safe copy (deep clone) of property value object 
when creating copy of Exchange objects.
  * Classes implementing this interface can be set as key value pair on 
exchange object via
- * {@link ExtendedExchange#setSafeCopyProperty(String, SafeCopyProperty)}.
+ * {@link ExchangeExtension#setSafeCopyProperty(String, SafeCopyProperty)}.
  *
  * When exchange object is copied it will invoke {@link 
SafeCopyProperty#safeCopy()} method on properties set using
- * {@link ExtendedExchange#setSafeCopyProperty(String, SafeCopyProperty)}. 
This allows the property value object to
+ * {@link ExchangeExtension#setSafeCopyProperty(String, SafeCopyProperty)}. 
This allows the property value object to
  * return a copy object to be set on the target exchange object instead of the 
original value object. This protects the
  * properties from unintended mutation when using parallelProcessing in 
Multicast or RecipientList EIP
  */
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java
index 6e480f18227..7b1a48aa85f 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java
@@ -30,6 +30,7 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.CamelExecutionException;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
+import org.apache.camel.ExchangeExtension;
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.ExchangePropertyKey;
 import org.apache.camel.ExtendedCamelContext;
@@ -54,7 +55,6 @@ import static org.apache.camel.support.MessageHelper.copyBody;
  * @see DefaultExchange
  */
 class AbstractExchange implements ExtendedExchange {
-
     // number of elements in array
     static final int INTERNAL_LENGTH = ExchangePropertyKey.values().length;
     // empty array for reset
@@ -90,17 +90,19 @@ class AbstractExchange implements ExtendedExchange {
     Boolean errorHandlerHandled;
     AsyncCallback defaultConsumerCallback; // optimize (do not reset)
     Map<String, SafeCopyProperty> safeCopyProperties;
+    private final ExtendedExchangeExtension privateExtension;
+
 
     public AbstractExchange(CamelContext context) {
-        this.context = context;
-        this.pattern = ExchangePattern.InOnly;
-        this.created = System.currentTimeMillis();
+        this(context, ExchangePattern.InOnly);
     }
 
     public AbstractExchange(CamelContext context, ExchangePattern pattern) {
         this.context = context;
         this.pattern = pattern;
         this.created = System.currentTimeMillis();
+
+        privateExtension = new ExtendedExchangeExtension(this);
     }
 
     public AbstractExchange(Exchange parent) {
@@ -110,6 +112,8 @@ class AbstractExchange implements ExtendedExchange {
         this.fromEndpoint = parent.getFromEndpoint();
         this.fromRouteId = parent.getFromRouteId();
         this.unitOfWork = parent.getUnitOfWork();
+
+        privateExtension = new ExtendedExchangeExtension(this);
     }
 
     public AbstractExchange(Endpoint fromEndpoint) {
@@ -117,6 +121,8 @@ class AbstractExchange implements ExtendedExchange {
         this.pattern = fromEndpoint.getExchangePattern();
         this.created = System.currentTimeMillis();
         this.fromEndpoint = fromEndpoint;
+
+        privateExtension = new ExtendedExchangeExtension(this);
     }
 
     public AbstractExchange(Endpoint fromEndpoint, ExchangePattern pattern) {
@@ -124,6 +130,8 @@ class AbstractExchange implements ExtendedExchange {
         this.pattern = pattern;
         this.created = System.currentTimeMillis();
         this.fromEndpoint = fromEndpoint;
+
+        privateExtension = new ExtendedExchangeExtension(this);
     }
 
     @Override
@@ -970,4 +978,10 @@ class AbstractExchange implements ExtendedExchange {
         return ExchangeHelper.convertToType(this, type, value);
     }
 
+
+    public ExtendedExchangeExtension getExchangeExtension() {
+        return privateExtension;
+    }
+
+
 }
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/ExtendedExchangeExtension.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/ExtendedExchangeExtension.java
new file mode 100644
index 00000000000..318bac4902e
--- /dev/null
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/ExtendedExchangeExtension.java
@@ -0,0 +1,216 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.support;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangeExtension;
+import org.apache.camel.SafeCopyProperty;
+import org.apache.camel.spi.Synchronization;
+import org.apache.camel.spi.UnitOfWork;
+
+public class ExtendedExchangeExtension implements ExchangeExtension {
+    private final AbstractExchange exchange;
+
+    ExtendedExchangeExtension(AbstractExchange exchange) {
+        this.exchange = exchange;
+    }
+
+    @Override
+    public void setFromEndpoint(Endpoint fromEndpoint) {
+        this.exchange.fromEndpoint = fromEndpoint;
+    }
+
+    @Override
+    public void setFromRouteId(String fromRouteId) {
+        exchange.fromRouteId = fromRouteId;
+    }
+
+    /**
+     * Is stream caching disabled on the given exchange
+     */
+    public boolean isStreamCacheDisabled() {
+        return this.exchange.streamCacheDisabled;
+    }
+
+    /**
+     * Used to force disabling stream caching which some components can do in 
special use-cases.
+     */
+    public void setStreamCacheDisabled(boolean streamCacheDisabled) {
+        this.exchange.streamCacheDisabled = streamCacheDisabled;
+    }
+
+    @Override
+    public void addOnCompletion(Synchronization onCompletion) {
+        this.exchange.addOnCompletion(onCompletion);
+    }
+
+    @Override
+    public boolean isErrorHandlerHandledSet() {
+        return this.exchange.isErrorHandlerHandledSet();
+    }
+
+    @Override
+    public Boolean getErrorHandlerHandled() {
+        return this.exchange.errorHandlerHandled;
+    }
+
+    @Override
+    public void setErrorHandlerHandled(Boolean errorHandlerHandled) {
+        this.exchange.errorHandlerHandled = errorHandlerHandled;
+    }
+
+    @Override
+    public boolean isErrorHandlerHandled() {
+        return this.exchange.errorHandlerHandled;
+    }
+
+    @Override
+    public boolean isRedeliveryExhausted() {
+        return this.exchange.redeliveryExhausted;
+    }
+
+    @Override
+    public void setRedeliveryExhausted(boolean redeliveryExhausted) {
+        this.exchange.redeliveryExhausted = redeliveryExhausted;
+    }
+
+    @Override
+    public void handoverCompletions(Exchange target) {
+        this.exchange.handoverCompletions(target);
+    }
+
+    @Override
+    public List<Synchronization> handoverCompletions() {
+        return this.exchange.handoverCompletions();
+    }
+
+    @Override
+    public void setUnitOfWork(UnitOfWork unitOfWork) {
+        this.exchange.setUnitOfWork(unitOfWork);
+    }
+
+    @Override
+    public void copyInternalProperties(Exchange target) {
+        this.exchange.copyInternalProperties(target);
+    }
+
+    @Override
+    public void setProperties(Map<String, Object> properties) {
+        this.exchange.setProperties(properties);
+    }
+
+    @Override
+    public void setHistoryNodeId(String historyNodeId) {
+        this.exchange.historyNodeId = historyNodeId;
+    }
+
+    @Override
+    public String getHistoryNodeId() {
+        return this.exchange.historyNodeId;
+    }
+
+    @Override
+    public String getHistoryNodeSource() {
+        return this.exchange.historyNodeSource;
+    }
+
+    @Override
+    public void setHistoryNodeSource(String historyNodeSource) {
+        this.exchange.historyNodeSource = historyNodeSource;
+    }
+
+    @Override
+    public String getHistoryNodeLabel() {
+        return this.exchange.historyNodeSource;
+    }
+
+    @Override
+    public void setHistoryNodeLabel(String historyNodeLabel) {
+        this.exchange.historyNodeLabel = historyNodeLabel;
+    }
+
+    @Override
+    public boolean isNotifyEvent() {
+        return this.exchange.notifyEvent;
+    }
+
+    @Override
+    public void setNotifyEvent(boolean notifyEvent) {
+        this.exchange.notifyEvent = notifyEvent;
+    }
+
+    @Override
+    public Map<String, Object> getInternalProperties() {
+        return this.exchange.getInternalProperties();
+    }
+
+    @Override
+    public boolean containsOnCompletion(Synchronization onCompletion) {
+        return this.exchange.containsOnCompletion(onCompletion);
+    }
+
+    @Override
+    public void setTransacted(boolean transacted) {
+        this.exchange.transacted = transacted;
+    }
+
+    @Override
+    public void setInterruptable(boolean interruptable) {
+        this.exchange.interruptable = interruptable;
+    }
+
+    @Override
+    public boolean isInterrupted() {
+        return this.exchange.interrupted;
+    }
+
+    @Override
+    public void setInterrupted(boolean interrupted) {
+        this.exchange.setInterrupted(interrupted);
+    }
+
+    @Override
+    public <T> T getInOrNull(Class<T> type) {
+        return this.exchange.getInOrNull(type);
+    }
+
+    @Override
+    public AsyncCallback getDefaultConsumerCallback() {
+        return this.exchange.defaultConsumerCallback;
+    }
+
+    @Override
+    public void setDefaultConsumerCallback(AsyncCallback callback) {
+        this.exchange.defaultConsumerCallback = callback;
+    }
+
+    @Override
+    public void setSafeCopyProperty(String key, SafeCopyProperty value) {
+        this.exchange.setSafeCopyProperty(key, value);
+    }
+
+    @Override
+    public <T> T getSafeCopyProperty(String key, Class<T> type) {
+        return this.exchange.getSafeCopyProperty(key, type);
+    }
+}

Reply via email to