svn commit: r756742 [1/2] - in /camel/branches/camel-1.x/components/camel-cxf: ./ src/main/java/org/apache/camel/component/cxf/ src/main/java/org/apache/camel/component/cxf/headers/ src/test/java/org/apache/camel/component/cxf/soap/ src/test/java/org/a...

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r756742 [1/2] - in /camel/branches/camel-1.x/components/camel-cxf: ./ src/main/java/org/apache/camel/component/cxf/ src/main/java/org/apache/camel/component/cxf/headers/ src/test/java/org/apache/camel/component/cxf/soap/ src/test/java/org/a...

wtam-2
Author: wtam
Date: Fri Mar 20 20:07:40 2009
New Revision: 756742

URL: http://svn.apache.org/viewvc?rev=756742&view=rev
Log:
[CAMEL-1474] On the wire headers are dropped inside camel route between two CxfEndpoints

Added:
    camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/
    camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/DefaultMessageHeadersRelay.java   (with props)
    camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/Direction.java   (with props)
    camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/MessageHeadersRelay.java   (with props)
    camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/SoapMessageHeadersRelay.java   (with props)
    camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/
    camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/
    camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/Constants.java   (with props)
    camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CustomHeadersRelay.java   (with props)
    camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CxfMessageHeadersRelayTest.java   (with props)
    camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/HeaderTesterImpl.java   (with props)
    camel/branches/camel-1.x/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/spring/message_headers_relay.xml   (with props)
    camel/branches/camel-1.x/components/camel-cxf/src/test/resources/soap_header.wsdl   (with props)
Modified:
    camel/branches/camel-1.x/components/camel-cxf/pom.xml
    camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CamelInvoker.java
    camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfBinding.java
    camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfConstants.java
    camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfEndpoint.java
    camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfProducer.java

Modified: camel/branches/camel-1.x/components/camel-cxf/pom.xml
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/pom.xml?rev=756742&r1=756741&r2=756742&view=diff
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/pom.xml (original)
+++ camel/branches/camel-1.x/components/camel-cxf/pom.xml Fri Mar 20 20:07:40 2009
@@ -269,6 +269,12 @@
        </extraargs>
        </wsdlOption>
        <wsdlOption>
+       <wsdl>${basedir}/src/test/resources/soap_header.wsdl</wsdl>
+       <extraargs>
+       <extraarg>-verbose</extraarg>
+       </extraargs>
+       </wsdlOption>
+       <wsdlOption>
        <wsdl>${basedir}/src/test/resources/person-non-wrapper.wsdl</wsdl>
        <extraargs>
        <extraarg>-b</extraarg>

Modified: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CamelInvoker.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CamelInvoker.java?rev=756742&r1=756741&r2=756742&view=diff
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CamelInvoker.java (original)
+++ camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CamelInvoker.java Fri Mar 20 20:07:40 2009
@@ -26,8 +26,10 @@
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.component.cxf.util.CxfHeaderHelper;
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.endpoint.Client;
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.frontend.MethodDispatcher;
+import org.apache.cxf.headers.Header;
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.message.Exchange;
@@ -174,6 +176,7 @@
         CxfHeaderHelper.propagateCxfToCamel(endpoint.getHeaderFilterStrategy(), exchange.getInMessage(),
                 cxfExchange.getIn().getHeaders());
         cxfExchange.getIn().setBody(params);
+        
         try {
             cxfConsumer.getProcessor().process(cxfExchange);
         } catch (Exception ex) {
@@ -193,6 +196,24 @@
                 throw new Fault(ex);
             }
         } else {
+            Message cxfMessage = exchange.getOutMessage();
+            if (cxfMessage == null && !exchange.isOneWay()) {
+                Endpoint ep = exchange.get(Endpoint.class);
+                cxfMessage = ep.getBinding().createMessage();
+                exchange.setOutMessage(cxfMessage);
+            }
+
+            Message message = cxfExchange.getOutMessage();
+            if (message != null) {
+                Map<String, Object> responseContext = CastUtils.cast((Map<?, ?>)message.get(Client.RESPONSE_CONTEXT));
+                if (responseContext != null) {
+                    List<Header> headers = CastUtils.cast((List<?>)responseContext.get(Header.HEADER_LIST));
+                    if (headers != null) {
+                        cxfMessage.put(Header.HEADER_LIST, headers);
+                    }
+                }
+            }
+
             result = cxfExchange.getOut().getBody();
             if (result != null) {
                 if (result instanceof MessageContentsList || result instanceof List || result.getClass().isArray()) {

Modified: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfBinding.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfBinding.java?rev=756742&r1=756741&r2=756742&view=diff
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfBinding.java (original)
+++ camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfBinding.java Fri Mar 20 20:07:40 2009
@@ -17,22 +17,38 @@
 package org.apache.camel.component.cxf;
 
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
+import javax.xml.ws.Holder;
 import javax.xml.ws.handler.MessageContext;
 import javax.xml.ws.handler.MessageContext.Scope;
 
 import org.apache.camel.NoTypeConversionAvailableException;
+import org.apache.camel.component.cxf.headers.DefaultMessageHeadersRelay;
+import org.apache.camel.component.cxf.headers.Direction;
+import org.apache.camel.component.cxf.headers.MessageHeadersRelay;
 import org.apache.camel.component.cxf.util.CxfHeaderHelper;
 import org.apache.camel.spi.HeaderFilterStrategy;
+import org.apache.cxf.binding.Binding;
+import org.apache.cxf.binding.soap.model.SoapHeaderInfo;
+import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.endpoint.Endpoint;
+import org.apache.cxf.headers.Header;
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.jaxws.context.WrappedMessageContext;
 import org.apache.cxf.jaxws.handler.HandlerChainInvoker;
+import org.apache.cxf.message.Exchange;
 import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageContentsList;
+import org.apache.cxf.service.model.BindingMessageInfo;
+import org.apache.cxf.service.model.BindingOperationInfo;
 
 /**
  * The binding/mapping of Camel messages to Apache CXF and back again
@@ -40,6 +56,8 @@
  * @version $Revision$
  */
 public final class CxfBinding {
+    private static final Logger LOG = LogUtils.getL7dLogger(CxfBinding.class);
+    
     private CxfBinding() {
         // Helper class
     }
@@ -111,7 +129,7 @@
         requestContext.remove(HandlerChainInvoker.class.getName());
         
         answer.put(Client.REQUEST_CONTEXT, requestContext);
-
+        
         return answer;
     }
 
@@ -192,35 +210,185 @@
     }
 
 
-    public static Map<String, Object> propogateContext(Message message, Map<String, Object> context) {
-        Map<String, Object> requestContext = CastUtils.cast((Map)message.get(Client.REQUEST_CONTEXT));
-        Map<String, Object> responseContext = CastUtils.cast((Map)message.get(Client.RESPONSE_CONTEXT));
-        // TODO map the JAXWS properties to cxf
+    public static Map<String, Object> propogateContext(CxfExchange exchange, Map<String, Object> context) {
+        Message message = exchange.getInMessage();
+        Map<String, Object> requestContext = CastUtils.cast((Map<?, ?>)message.get(Client.REQUEST_CONTEXT));
+        Map<String, Object> responseContext = CastUtils.cast((Map<?, ?>)message.get(Client.RESPONSE_CONTEXT));
+        Map<String, Object> camelRequestContext =
+            CastUtils.cast((Map<?, ?>)exchange.getIn().getHeader(Client.REQUEST_CONTEXT));
+        
+        Map<String, Object> mergedRequestContext = new HashMap<String, Object>();
+        WrappedMessageContext ctx = new WrappedMessageContext(mergedRequestContext,
+                                                              null,
+                                                              Scope.APPLICATION);
         if (requestContext != null) {
-            Map<String, Object> realMap = new HashMap<String, Object>();
-            WrappedMessageContext ctx = new WrappedMessageContext(realMap,
-                                                                  null,
-                                                                  Scope.APPLICATION);
             ctx.putAll(requestContext);
-
-            // Remove protocol headers from scopes.  Otherwise, response headers can be
-            // overwritten by request headers when SOAPHandlerInterceptor tries to create
-            // a wrapped message context by the copyScoped() method.
+        }
+        
+        if (camelRequestContext != null) {
+            ctx.putAll(camelRequestContext);
+        }
+        
+        // Remove protocol headers from scopes.  Otherwise, response headers can be
+        // overwritten by request headers when SOAPHandlerInterceptor tries to create
+        // a wrapped message context by the copyScoped() method.
+        if (ctx.size() > 0) {
             ctx.getScopes().remove(Message.PROTOCOL_HEADERS);
-            requestContext = realMap;
-
         }
-
+            
         if (responseContext == null) {
             responseContext = new HashMap<String, Object>();
         } else {
             // clear the response context
             responseContext.clear();
         }
-        context.put(Client.REQUEST_CONTEXT, requestContext);
+        context.put(Client.REQUEST_CONTEXT, mergedRequestContext);
         context.put(Client.RESPONSE_CONTEXT, responseContext);
         return responseContext;
-
     }
 
+    protected static void relayRequestHeaders(CxfEndpoint endpoint,
+                                              CxfExchange exchange,
+                                              Map<String, Object> context) {
+        
+        Message message = exchange.getInMessage();
+        if (message == null) {
+            return;
+        }
+        Map<String, Object> requestContext = CastUtils.cast((Map<?, ?>)context.get(Client.REQUEST_CONTEXT));
+        if (!endpoint.isRelayHeaders()) {
+            message.remove(Header.HEADER_LIST);
+            if (exchange.getExchange() == null) {
+                return;
+            }
+            BindingOperationInfo bop = exchange.getExchange().get(BindingOperationInfo.class);
+            if (null == bop) {
+                return;
+            }
+            BindingMessageInfo bmi = bop.getInput();
+            List<SoapHeaderInfo> headersInfo = bmi.getExtensors(SoapHeaderInfo.class);
+            if (headersInfo == null || headersInfo.size() == 0) {
+                return;
+            }
+            MessageContentsList parameters = MessageContentsList.getContentsList(message);
+            for (SoapHeaderInfo headerInfo : headersInfo) {
+                Object o = parameters.get(headerInfo.getPart());
+                if (o instanceof Holder) {
+                    Holder holder = (Holder)o;
+                    holder.value = null;
+                } else {
+                    parameters.remove(headerInfo.getPart());
+                }
+            }
+            return;
+        }
+        if (!message.containsKey(Header.HEADER_LIST)) {
+            return;
+        }
+        MessageHeadersRelay relay = getRelay(endpoint, exchange);
+        relayHeaders(Direction.OUT,
+                     (List<Header>)message.get(Header.HEADER_LIST),
+                     requestContext,
+                     relay);
+    }
+
+    protected static void relayResponseHeaders(CxfEndpoint endpoint,
+                                               CxfExchange exchange,
+                                               Map<String, Object> context) {
+        Message message = exchange.getOutMessage();
+        if (message == null) {
+            return;
+        }
+        Map<String, Object> responseContext = (Map<String, Object>)context.get(Client.RESPONSE_CONTEXT);
+        List<Header> headers = (List<Header>)responseContext.get(Header.HEADER_LIST);
+        responseContext.remove(Header.HEADER_LIST);
+        if (!endpoint.isRelayHeaders()) {
+            Exchange e = exchange.getExchange();
+            if (e == null) {
+                return;
+            }
+            BindingOperationInfo bop = e.get(BindingOperationInfo.class);
+            if (null == bop) {
+                return;
+            }
+            BindingMessageInfo bmi = bop.getOutput();
+            List<SoapHeaderInfo> headersInfo = bmi.getExtensors(SoapHeaderInfo.class);
+            if (headersInfo == null || headersInfo.size() == 0) {
+                return;
+            }
+            MessageContentsList parameters = MessageContentsList.getContentsList(message);
+            for (SoapHeaderInfo headerInfo : headersInfo) {
+                Object o = parameters.get(headerInfo.getPart());
+                if (o instanceof Holder) {
+                    Holder holder = (Holder)o;
+                    holder.value = null;
+                } else {
+                    parameters.remove(headerInfo.getPart());
+                }
+            }
+            return;
+        }
+        if (headers == null || headers.size() == 0) {
+            return;
+        }
+        MessageHeadersRelay relay = getRelay(endpoint, exchange);
+        relayHeaders(Direction.IN,
+                     headers,
+                     responseContext,
+                     relay);
+    }
+
+    protected static MessageHeadersRelay getRelay(CxfEndpoint endpoint, CxfExchange exchange) {
+        MessageHeadersRelay relay = null;
+        String ns = null;
+        Endpoint e = null;
+        Exchange cxfExchange = exchange.getExchange();
+        if (cxfExchange != null) {
+            e = cxfExchange.get(Endpoint.class);
+        }
+        if (e != null && e.getBinding() != null) {
+            Binding b = e.getBinding();
+            if (b != null && b.getBindingInfo() != null) {
+                ns = b.getBindingInfo().getBindingId();
+            }
+        }
+        if (ns == null) {
+            LOG.log(Level.WARNING,
+                    "No CXF Binding namespace can be resolved for relaying message headers, "
+                     + " using " + DefaultMessageHeadersRelay.ACTIVATION_NAMESPACE + " namespace");
+        }
+        if (ns != null) {
+            relay = endpoint.getMessageHeadersRelay(ns);
+        }
+        if (relay == null) {
+            LOG.log(Level.WARNING,
+                    "No MessageHeadersRelay instance is bound to '"
+                     + ns + "' namespace; using "
+                     + DefaultMessageHeadersRelay.ACTIVATION_NAMESPACE + " namespace");
+            relay =
+                endpoint.getMessageHeadersRelay(DefaultMessageHeadersRelay.ACTIVATION_NAMESPACE);
+        }
+        return relay;
+    }
+    
+    protected static void relayHeaders(Direction direction,
+                                       List<Header> from,
+                                       Map<String, Object> context,
+                                       MessageHeadersRelay relay) {
+        
+        List<Header> to = (List<Header>)context.get(Header.HEADER_LIST);
+        boolean hasHeaders = true;
+        if (to == null) {
+            to = new ArrayList<Header>();
+            hasHeaders = false;
+        }
+        relay.relay(direction, from, to);
+        for (Header header : to) {
+            header.setDirection(Header.Direction.DIRECTION_OUT);
+        }
+        if (!hasHeaders && to.size() > 0) {
+            context.put(Header.HEADER_LIST, to);
+        }
+    }
 }
+

Modified: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfConstants.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfConstants.java?rev=756742&r1=756741&r2=756742&view=diff
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfConstants.java (original)
+++ camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfConstants.java Fri Mar 20 20:07:40 2009
@@ -41,6 +41,7 @@
     String CAMEL_TRANSPORT_PREFIX = "camel:";
     String CXF_EXCHANGE = "org.apache.cxf.message.exchange";
     String CAMEL_EXCHANGE = "org.apache.camel.exchange";
+    String CAMEL_CXF_MESSAGE_HEADER_RELAYS = "org.apache.camel.cxf.message.headers.relays";
 }
 
 

Modified: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfEndpoint.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfEndpoint.java?rev=756742&r1=756741&r2=756742&view=diff
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfEndpoint.java (original)
+++ camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfEndpoint.java Fri Mar 20 20:07:40 2009
@@ -16,16 +16,26 @@
  */
 package org.apache.camel.component.cxf;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.camel.Consumer;
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
+import org.apache.camel.component.cxf.headers.DefaultMessageHeadersRelay;
+import org.apache.camel.component.cxf.headers.MessageHeadersRelay;
+import org.apache.camel.component.cxf.headers.SoapMessageHeadersRelay;
 import org.apache.camel.component.cxf.spring.CxfEndpointBean;
 import org.apache.camel.impl.DefaultEndpoint;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.spring.SpringCamelContext;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.cxf.configuration.spring.ConfigurerImpl;
+import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.message.Message;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.support.AbstractApplicationContext;
@@ -49,16 +59,20 @@
     private boolean isWrapped;
     private boolean isSpringContextEndpoint;
     private boolean inOut = true;
+    private boolean relayHeaders = true;
+
     private Boolean isSetDefaultBus;
     private ConfigurerImpl configurer;
     private CxfEndpointBean cxfEndpointBean;
-
+
+    private Map<String, MessageHeadersRelay> ns2Relay = new HashMap<String, MessageHeadersRelay>();
 
 
     public CxfEndpoint(String uri, String address, CxfComponent component) {
         super(uri, component);
         this.component = component;
         this.address = address;
+        
         if (address.startsWith(CxfConstants.SPRING_CONTEXT_ENDPOINT)) {
             isSpringContextEndpoint = true;
             // Get the bean from the Spring context
@@ -71,6 +85,8 @@
             cxfEndpointBean = (CxfEndpointBean) context.getApplicationContext().getBean(beanId);
             ObjectHelper.notNull(cxfEndpointBean, "cxfEndpointBean");
         }
+        
+        initializeHeadersRelaysMap();
     }
 
     public Producer<CxfExchange> createProducer() throws Exception {
@@ -165,6 +181,14 @@
         this.inOut = inOut;
     }
 
+    public boolean isRelayHeaders() {
+        return relayHeaders;
+    }
+
+    public void setRelayHeaders(boolean relayHeaders) {
+        this.relayHeaders = relayHeaders;
+    }
+
     public boolean isWrapped() {
         return isWrapped;
     }
@@ -185,7 +209,7 @@
     public String getBeanId() {
         return beanId;
     }
-
+    
     public CxfEndpointBean getCxfEndpointBean() {
         return cxfEndpointBean;
     }
@@ -214,4 +238,67 @@
         return component.getHeaderFilterStrategy();
     }
 
+    // adds new relays and makes sure that none of newly added relays
+    // have a matching activation namespace
+    public void setMessageHeadersRelay(Collection<MessageHeadersRelay> relays) {
+        Map<String, MessageHeadersRelay> localRelays = new HashMap<String, MessageHeadersRelay>();
+        for (MessageHeadersRelay relay : relays) {
+            setMessageHeadersRelay(relay, localRelays, false);
+        }
+        // once we verified that namespaces are represented by one and only relay
+        // allow to replace old relays with new ones for a given namespace
+        ns2Relay.putAll(localRelays);
+    }
+
+    public Collection<MessageHeadersRelay> getMessageHeadersRelays() {
+        Collection<MessageHeadersRelay> relays = new ArrayList<MessageHeadersRelay>();
+        for (MessageHeadersRelay relay : ns2Relay.values()) {
+            if (!relays.contains(relay)) {
+                relays.add(relay);
+            }
+        }
+        return relays;
+    }
+    
+    public MessageHeadersRelay getMessageHeadersRelay(String ns) {
+        return ns2Relay.get(ns);
+    }
+
+    protected void initializeHeadersRelaysMap() {
+        Collection<MessageHeadersRelay> defaultRelays = new ArrayList<MessageHeadersRelay>();
+        defaultRelays.addAll(Arrays.asList(new DefaultMessageHeadersRelay(), new SoapMessageHeadersRelay()));
+        
+        setMessageHeadersRelay(defaultRelays);
+        
+        if (cxfEndpointBean == null || cxfEndpointBean.getProperties() == null) {
+            return;
+        }
+        Object v = cxfEndpointBean.getProperties().get(CxfConstants.CAMEL_CXF_MESSAGE_HEADER_RELAYS);
+        if (v == null || !(v instanceof Collection)) {
+            return;
+        }
+        Collection<?> c = (Collection<?>)v;
+        Collection<MessageHeadersRelay> relays = null;
+        try {
+            relays = CastUtils.cast((Collection<?>)c);
+        } catch (ClassCastException e) {
+            throw new IllegalArgumentException("The property "
+                                               + CxfConstants.CAMEL_CXF_MESSAGE_HEADER_RELAYS
+                                               + " must have a list that consists of classes inherited from "
+                                               + MessageHeadersRelay.class.getName());
+        }
+        setMessageHeadersRelay(relays);    
+    }
+
+    private static void setMessageHeadersRelay(MessageHeadersRelay relay,
+                                               Map<String, MessageHeadersRelay> ns2Relay,
+                                               boolean allowClash) {
+        for (String ns : relay.getActivationNamespaces()) {
+            if (ns2Relay.containsKey(ns) && ns2Relay.get(ns) != relay && !allowClash) {
+                throw new IllegalArgumentException("More then one MessageHeaderRelay activates "
+                                                   + "for the same namespace: " + ns);
+            }
+            ns2Relay.put(ns, relay);
+        }
+    }
 }

Modified: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfProducer.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfProducer.java?rev=756742&r1=756741&r2=756742&view=diff
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfProducer.java (original)
+++ camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfProducer.java Fri Mar 20 20:07:40 2009
@@ -21,6 +21,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.logging.Logger;
 
 import javax.xml.namespace.QName;
 
@@ -33,16 +34,13 @@
 import org.apache.camel.component.cxf.invoker.CxfClientFactoryBean;
 import org.apache.camel.component.cxf.invoker.InvokingContext;
 import org.apache.camel.component.cxf.invoker.InvokingContextFactory;
-import org.apache.camel.component.cxf.spring.CxfEndpointBean;
 import org.apache.camel.component.cxf.util.CxfEndpointUtils;
 import org.apache.camel.impl.DefaultProducer;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.cxf.Bus;
 import org.apache.cxf.BusFactory;
 import org.apache.cxf.bus.spring.SpringBusFactory;
-import org.apache.cxf.common.classloader.ClassLoaderUtils;
-import org.apache.cxf.configuration.Configurer;
-import org.apache.cxf.configuration.spring.ConfigurerImpl;
+import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.endpoint.Client;
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.frontend.ClientProxy;
@@ -60,6 +58,9 @@
  * @version $Revision$
  */
 public class CxfProducer extends DefaultProducer<CxfExchange> {
+    
+    private static final Logger LOG = LogUtils.getL7dLogger(CxfProducer.class);
+    
     private CxfEndpoint endpoint;
     private Client client;
     private DataFormat dataFormat;
@@ -173,7 +174,10 @@
                                                                    String.class);
             // Get context from message
             Map<String, Object> context = new HashMap<String, Object>();
-            Map<String, Object> responseContext = CxfBinding.propogateContext(inMessage, context);
+            Map<String, Object> responseContext = CxfBinding.propogateContext(exchange, context);
+            
+            CxfBinding.relayRequestHeaders(endpoint, exchange, context);
+            
             Message response = new MessageImpl();
             if (operationName != null) {
                 // we need to check out the operation Namespace
@@ -188,6 +192,7 @@
                 // copy the response context to the response
                 CxfBinding.storeCXfResponseContext(response, responseContext);
                 CxfBinding.storeCxfResponse(endpoint.getHeaderFilterStrategy(), exchange, response);
+                CxfBinding.relayResponseHeaders(endpoint, exchange, context);
 
             } else {
                 throw new RuntimeCamelException("Can't find the operation name in the message!");
@@ -226,7 +231,7 @@
             response.setExchange(ex);
             // invoke the message prepare the context
             Map<String, Object> context = new HashMap<String, Object>();
-            Map<String, Object> responseContext = CxfBinding.propogateContext(inMessage, context);
+            Map<String, Object> responseContext = CxfBinding.propogateContext(exchange, context);
 
             Object result = cxfClient.dispatch(params, context, ex);
             ex.setOutMessage(response);
@@ -234,8 +239,6 @@
             // copy the response context to the response
             CxfBinding.storeCXfResponseContext(response, responseContext);
             CxfBinding.storeCxfResponse(endpoint.getHeaderFilterStrategy(), exchange, response);
-
-
         }
 
     }

Added: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/DefaultMessageHeadersRelay.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/DefaultMessageHeadersRelay.java?rev=756742&view=auto
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/DefaultMessageHeadersRelay.java (added)
+++ camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/DefaultMessageHeadersRelay.java Fri Mar 20 20:07:40 2009
@@ -0,0 +1,45 @@
+/**
+ * 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.component.cxf.headers;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.cxf.headers.Header;
+
+public class DefaultMessageHeadersRelay implements MessageHeadersRelay {
+    
+    public static final String ACTIVATION_NAMESPACE = "http://cxf.apache.org/bindings";
+    public static final List<String> ACTIVATION_NAMESPACES = Arrays.asList(ACTIVATION_NAMESPACE);
+
+    public DefaultMessageHeadersRelay() {
+    }
+
+    public List<String> getActivationNamespaces() {
+        return ACTIVATION_NAMESPACES;
+    }
+    
+    /*
+     * simply relay all headers  
+     */
+    public void relay(Direction direction, List<Header> from, List<Header> to) {
+        for (Header header : from) {
+            to.add(header);
+        }
+    }
+}

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/DefaultMessageHeadersRelay.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/DefaultMessageHeadersRelay.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/Direction.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/Direction.java?rev=756742&view=auto
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/Direction.java (added)
+++ camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/Direction.java Fri Mar 20 20:07:40 2009
@@ -0,0 +1,23 @@
+/**
+ * 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.component.cxf.headers;
+
+public enum Direction {
+    IN,
+    OUT
+}

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/Direction.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/Direction.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/MessageHeadersRelay.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/MessageHeadersRelay.java?rev=756742&view=auto
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/MessageHeadersRelay.java (added)
+++ camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/MessageHeadersRelay.java Fri Mar 20 20:07:40 2009
@@ -0,0 +1,52 @@
+/**
+ * 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.component.cxf.headers;
+
+import java.util.List;
+
+import org.apache.cxf.headers.Header;
+
+/*
+ * Relays the wire message headers from one CXF endpoint to another CXF endpoint
+ * Direction.OUT specifies when headers are relayed from a CXF consumer to producer (request)
+ * Direction.IN specifies when headers are relayed from a CXF producer to CXF consumer (reply)
+ * */
+public interface MessageHeadersRelay {
+
+    /*
+     * @return a list of binding name spaces that this relay can service
+     */
+    List<String> getActivationNamespaces();
+
+    /*
+     *  Given a route:
+     *      from(cxf:cxf:bean:A).to(cxf:bean:B)
+     *  
+     *  A message flow (request) from A to B will be treated as Direction.OUT direction;
+     *  @param direction = Direction.OUT
+     *  @param from is message headers for endpoint A
+     *  @param to is message headers for endpoint B
+     *  
+     *  A message flow (reply) from B to A will be treated as Direction.IN direction  
+     *  @param direction = Direction.IN
+     *  @param from is message headers for endpoint B
+     *  @param to is message headers for endpoint A
+     *  
+     */
+    void relay(Direction direction, List<Header> from, List<Header> to);
+}

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/MessageHeadersRelay.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/MessageHeadersRelay.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/SoapMessageHeadersRelay.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/SoapMessageHeadersRelay.java?rev=756742&view=auto
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/SoapMessageHeadersRelay.java (added)
+++ camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/SoapMessageHeadersRelay.java Fri Mar 20 20:07:40 2009
@@ -0,0 +1,71 @@
+/**
+ * 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.component.cxf.headers;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.cxf.binding.soap.SoapBindingConstants;
+import org.apache.cxf.binding.soap.SoapBindingFactory;
+import org.apache.cxf.binding.soap.SoapHeader;
+import org.apache.cxf.binding.soap.SoapVersion;
+import org.apache.cxf.binding.soap.SoapVersionFactory;
+import org.apache.cxf.headers.Header;
+
+public class SoapMessageHeadersRelay extends DefaultMessageHeadersRelay {
+
+    private static final List<String> ACTIVATION_NS =
+        Arrays.asList(SoapBindingConstants.SOAP11_BINDING_ID,
+                      SoapBindingFactory.SOAP_11_BINDING,
+                      SoapBindingFactory.SOAP_12_BINDING);
+    
+    public SoapMessageHeadersRelay() {
+    }
+    
+    public List<String> getActivationNamespaces() {
+        return ACTIVATION_NS;
+    }
+
+    public void relay(Direction direction, List<Header> from, List<Header> to) {
+        for (Iterator<Header> it = from.iterator(); it.hasNext();) {
+            Header header = it.next();
+            if (!(header instanceof SoapHeader)) {
+                continue;
+            }
+            SoapHeader soapHeader = SoapHeader.class.cast(header);
+            boolean dropped = false;
+            for (Iterator<SoapVersion> itv = SoapVersionFactory.getInstance().getVersions();
+                 itv.hasNext();) {
+                SoapVersion version = itv.next();
+                if (soapHeader.getActor() != null
+                    && soapHeader.getActor().equals(version.getNextRole())) {
+                    // dropping headers if actor/role equals to {ns}/role|actor/next
+                    // cxf SoapHeader needs to have soap:header@relay attribute,
+                    // then we can check for it here as well
+                    it.remove();
+                    dropped = true;
+                    break;
+                }
+            }
+            if (!dropped) {
+                to.add(header);
+            }
+        }
+    }
+}

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/SoapMessageHeadersRelay.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/headers/SoapMessageHeadersRelay.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/Constants.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/Constants.java?rev=756742&view=auto
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/Constants.java (added)
+++ camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/Constants.java Fri Mar 20 20:07:40 2009
@@ -0,0 +1,65 @@
+/**
+ * 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.component.cxf.soap.headers;
+
+public final class Constants {
+
+    public static final String TEST_HDR_NS = "http://cxf.apache.org/outofband/Header";
+    public static final String TEST_HDR_REQUEST_ELEM = "outofbandHeader";
+    public static final String TEST_HDR_RESPONSE_ELEM = "outofbandHeader";
+    public static final SOAPHeaderData IN_HEADER_DATA = new SOAPHeaderData();
+    public static final SOAPHeaderData OUT_HEADER_DATA = new SOAPHeaderData();
+    public static final SOAPHeaderData IN_OUT_REQUEST_HEADER_DATA = new SOAPHeaderData();
+    public static final SOAPHeaderData IN_OUT_RESPONSE_HEADER_DATA = new SOAPHeaderData();
+    
+    static {
+        IN_HEADER_DATA.setOriginator("CxfSoapHeaderRoutePropagationTest.testInHeader");        
+        IN_HEADER_DATA.setMessage("Invoking CxfSoapHeaderRoutePropagationTest.testInHeader()");
+        OUT_HEADER_DATA.setOriginator("CxfSoapHeaderRoutePropagationTest.testOutHeader");        
+        OUT_HEADER_DATA.setMessage("Invoking CxfSoapHeaderRoutePropagationTest.testOutHeader()");
+        IN_OUT_REQUEST_HEADER_DATA.setOriginator("CxfSoapHeaderRoutePropagationTest.testInOutHeader Requestor");        
+        IN_OUT_REQUEST_HEADER_DATA.setMessage("Invoking CxfSoapHeaderRoutePropagationTest.testInOutHeader() Request");
+        IN_OUT_RESPONSE_HEADER_DATA.setOriginator("CxfSoapHeaderRoutePropagationTest.testInOutHeader Responser");        
+        IN_OUT_RESPONSE_HEADER_DATA.setMessage("Invoking CxfSoapHeaderRoutePropagationTest.testInOutHeader() Responser");
+    }
+    
+    private Constants() {
+    }
+    
+    public static boolean equals(SOAPHeaderData lhs, SOAPHeaderData rhs) {
+        if (compare(lhs, rhs)) {
+            return true;
+        }
+        if (compare(lhs.getMessage(), rhs.getMessage())) {
+            return true;
+        }
+        if (compare(lhs.getOriginator(), rhs.getOriginator())) {
+            return true;
+        }
+        return false;
+    }
+    
+    public static <L, R> boolean compare(L lhs, R rhs) {
+        if (lhs == rhs) {
+            return true;
+        }
+        if (lhs == null || rhs == null && lhs != rhs) {
+            return false;
+        }
+        return lhs.equals(rhs);        
+    }
+}

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/Constants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/Constants.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CustomHeadersRelay.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CustomHeadersRelay.java?rev=756742&view=auto
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CustomHeadersRelay.java (added)
+++ camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CustomHeadersRelay.java Fri Mar 20 20:07:40 2009
@@ -0,0 +1,45 @@
+/**
+ * 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.component.cxf.soap.headers;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.camel.component.cxf.headers.Direction;
+import org.apache.camel.component.cxf.headers.MessageHeadersRelay;
+import org.apache.cxf.headers.Header;
+
+public class CustomHeadersRelay implements MessageHeadersRelay {
+
+    public static final String ACTIVATION_NAMESPACE = "http://cxf.apache.org/bindings/custom";
+    public static final List<String> ACTIVATION_NAMESPACES = Arrays.asList(ACTIVATION_NAMESPACE);
+
+    public CustomHeadersRelay() {
+    }
+
+    public List<String> getActivationNamespaces() {
+        return ACTIVATION_NAMESPACES;
+    }
+
+    public void relay(Direction direction, List<Header> from, List<Header> to) {
+        for (Header header : from) {
+            to.add(header);
+        }
+    }
+
+}

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CustomHeadersRelay.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CustomHeadersRelay.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CxfMessageHeadersRelayTest.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CxfMessageHeadersRelayTest.java?rev=756742&view=auto
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CxfMessageHeadersRelayTest.java (added)
+++ camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CxfMessageHeadersRelayTest.java Fri Mar 20 20:07:40 2009
@@ -0,0 +1,491 @@
+/**
+ * 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.component.cxf.soap.headers;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.namespace.QName;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.Endpoint;
+import javax.xml.ws.Holder;
+
+import org.w3c.dom.Node;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.component.cxf.CxfConstants;
+import org.apache.camel.component.cxf.CxfEndpoint;
+import org.apache.camel.component.cxf.headers.MessageHeadersRelay;
+import org.apache.camel.impl.DefaultExchange;
+import org.apache.camel.spring.SpringTestSupport;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.binding.soap.SoapHeader;
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.endpoint.ServerImpl;
+import org.apache.cxf.headers.Header;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.jaxb.JAXBDataBinding;
+import org.apache.cxf.jaxws.EndpointImpl;
+import org.apache.cxf.message.MessageContentsList;
+import org.apache.cxf.outofband.header.OutofBandHeader;
+import org.springframework.context.support.AbstractXmlApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+
+public class CxfMessageHeadersRelayTest extends SpringTestSupport {
+
+    private ServerImpl relayServer;
+    private ServerImpl noRelayServer;
+    
+    @Override
+    protected void setUp() throws Exception {
+        setUseRouteBuilder(false);
+        super.setUp();
+        startTargetCxfService();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (relayServer != null) {
+            relayServer.stop();
+        }
+        if (noRelayServer != null) {
+            noRelayServer.stop();
+        }        
+
+        super.tearDown();
+        BusFactory.setDefaultBus(null);
+    }
+
+    @Override
+    protected AbstractXmlApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/cxf/spring/message_headers_relay.xml");
+    }
+
+    protected void startTargetCxfService() {
+        Object impl = new HeaderTesterImpl();
+        String address = "http://localhost:9090/HeaderService/";
+        EndpointImpl endpoint = (EndpointImpl) Endpoint.publish(address, impl);
+        relayServer = endpoint.getServer();
+        
+        impl = new HeaderTesterImpl(false);
+        address = "http://localhost:7070/HeaderService/";
+        endpoint = (EndpointImpl) Endpoint.publish(address, impl);
+        noRelayServer = endpoint.getServer();
+    }
+
+    
+    protected static void addOutOfBoundHeader(HeaderTester proxy, boolean invalid) throws JAXBException {
+        InvocationHandler handler  = Proxy.getInvocationHandler(proxy);
+        BindingProvider  bp = null;
+
+        try {
+            if (handler instanceof BindingProvider) {
+                bp = (BindingProvider)handler;
+                Map<String, Object> requestContext = bp.getRequestContext();
+                requestContext.put(Header.HEADER_LIST, buildOutOfBandHeaderList(invalid));
+            }
+        } catch (JAXBException ex) {
+            throw ex;
+        }
+        
+    }
+  
+    protected static List<Header> buildOutOfBandHeaderList(boolean invalid) throws JAXBException {
+        OutofBandHeader ob = new OutofBandHeader();
+        ob.setName("testOobHeader");
+        ob.setValue("testOobHeaderValue");
+        ob.setHdrAttribute(invalid ? "dontProcess" : "testHdrAttribute");
+
+        SoapHeader hdr = new SoapHeader(
+                new QName(Constants.TEST_HDR_NS, Constants.TEST_HDR_REQUEST_ELEM),
+                ob,
+                new JAXBDataBinding(ob.getClass()));
+        hdr.setMustUnderstand(true);
+
+        List<Header> headers = new ArrayList<Header>();
+        headers.add(hdr);
+        return headers;
+    }
+    
+    public void testInHeaderCXFClientRelay() throws Exception {
+        HeaderService s = new HeaderService(getClass().getClassLoader().getResource("soap_header.wsdl"),
+                                            HeaderService.SERVICE);
+        HeaderTester proxy = s.getSoapPortRelay();
+        InHeader me = new InHeader();
+        me.setRequestType("CXF user");
+        InHeaderResponse response = proxy.inHeader(me, Constants.IN_HEADER_DATA);
+        assertTrue("Expected in band header to propagate but it didn't",
+                   response.getResponseType().equals("pass"));
+    }
+    
+    public void testOutHeaderCXFClientRelay() throws Exception {
+        HeaderService s = new HeaderService(getClass().getClassLoader().getResource("soap_header.wsdl"),
+                                            HeaderService.SERVICE);
+        HeaderTester proxy = s.getSoapPortRelay();
+        OutHeader me = new OutHeader();
+        me.setRequestType("CXF user");
+        Holder<OutHeaderResponse> result = new Holder<OutHeaderResponse>(new OutHeaderResponse());
+        Holder<SOAPHeaderData> header = new Holder<SOAPHeaderData>(new SOAPHeaderData());
+        proxy.outHeader(me, result, header);
+        assertTrue("Expected in band header to propagate but it didn't",
+                   result.value.getResponseType().equals("pass"));
+        assertTrue("Expected in band response header to propagate but it either didn't "
+                   + " or its contents do not match",
+                   Constants.equals(Constants.OUT_HEADER_DATA, header.value));
+    }
+
+    public void testInOutHeaderCXFClientRelay() throws Exception {
+        HeaderService s = new HeaderService(getClass().getClassLoader().getResource("soap_header.wsdl"),
+                                            HeaderService.SERVICE);
+        HeaderTester proxy = s.getSoapPortRelay();
+        InoutHeader me = new InoutHeader();
+        me.setRequestType("CXF user");
+        Holder<SOAPHeaderData> header = new Holder<SOAPHeaderData>(Constants.IN_OUT_REQUEST_HEADER_DATA);
+        InoutHeaderResponse result = proxy.inoutHeader(me, header);
+        assertTrue("Expected in band header to propagate but it didn't",
+                   result.getResponseType().equals("pass"));
+        assertTrue("Expected in band response header to propagate but it either didn't "
+                   + " or its contents do not match",
+                   Constants.equals(Constants.IN_OUT_RESPONSE_HEADER_DATA, header.value));
+    }
+
+    public void testInOutOfBandHeaderCXFClientRelay() throws Exception {
+        HeaderService s = new HeaderService(getClass().getClassLoader().getResource("soap_header.wsdl"),
+                                            HeaderService.SERVICE);
+        HeaderTester proxy = s.getSoapPortRelay();
+        addOutOfBoundHeader(proxy, false);
+        Me me = new Me();
+        me.setFirstName("john");
+        me.setLastName("Doh");
+        Me response = proxy.inOutOfBandHeader(me);
+        assertTrue("Expected the out of band header to propagate but it didn't",
+                   response.getFirstName().equals("pass"));
+    }
+    
+    public void testInoutOutOfBandHeaderCXFClientRelay() throws Exception {
+        HeaderService s = new HeaderService(getClass().getClassLoader().getResource("soap_header.wsdl"),
+                                            HeaderService.SERVICE);
+        HeaderTester proxy = s.getSoapPortRelay();
+        addOutOfBoundHeader(proxy, false);
+        Me me = new Me();
+        me.setFirstName("john");
+        me.setLastName("Doh");
+        Me response = proxy.inoutOutOfBandHeader(me);
+        assertTrue("Expected the out of band header to propagate but it didn't",
+                   response.getFirstName().equals("pass"));
+        validateReturnedOutOfBandHeader(proxy);
+    }
+
+    public void testOutOutOfBandHeaderCXFClientRelay() throws Exception {
+        HeaderService s = new HeaderService(getClass().getClassLoader().getResource("soap_header.wsdl"),
+                                            HeaderService.SERVICE);
+        HeaderTester proxy = s.getSoapPortRelay();
+        Me me = new Me();
+        me.setFirstName("john");
+        me.setLastName("Doh");
+        Me response = proxy.outOutOfBandHeader(me);
+        assertTrue("Expected the out of band header to propagate but it didn't",
+                   response.getFirstName().equals("pass"));
+        validateReturnedOutOfBandHeader(proxy);
+    }
+
+    public void testInOutOfBandHeaderCXFClientNoRelay() throws Exception {
+        HeaderService s = new HeaderService(getClass().getClassLoader().getResource("soap_header.wsdl"),
+                                            HeaderService.SERVICE);
+        HeaderTester proxy = s.getSoapPortNoRelay();
+        addOutOfBoundHeader(proxy, false);
+        Me me = new Me();
+        me.setFirstName("john");
+        me.setLastName("Doh");
+        Me response = proxy.inOutOfBandHeader(me);
+        assertTrue("Expected the in out of band header *not* to propagate but it did",
+                   response.getFirstName().equals("pass"));
+    }
+
+    public void testOutOutOfBandHeaderCXFClientNoRelay() throws Exception {
+        HeaderService s = new HeaderService(getClass().getClassLoader().getResource("soap_header.wsdl"),
+                                            HeaderService.SERVICE);
+        HeaderTester proxy = s.getSoapPortNoRelay();
+        Me me = new Me();
+        me.setFirstName("john");
+        me.setLastName("Doh");
+        Me response = proxy.outOutOfBandHeader(me);
+        assertTrue("Expected the out out of band header *not* to propagate but it did",
+                   response.getFirstName().equals("pass"));
+        validateReturnedOutOfBandHeader(proxy, false);
+    }
+
+    public void testInoutOutOfBandHeaderCXFClientNoRelay() throws Exception {
+        HeaderService s = new HeaderService(getClass().getClassLoader().getResource("soap_header.wsdl"),
+                                            HeaderService.SERVICE);
+        HeaderTester proxy = s.getSoapPortNoRelay();
+        addOutOfBoundHeader(proxy, false);
+        Me me = new Me();
+        me.setFirstName("john");
+        me.setLastName("Doh");
+        Me response = proxy.inoutOutOfBandHeader(me);
+        assertTrue("Expected the in out of band header to *not* propagate but it did",
+                   response.getFirstName().equals("pass"));
+        validateReturnedOutOfBandHeader(proxy, false);
+    }
+
+    public void testInHeaderCXFClientNoRelay() throws Exception {
+        HeaderService s = new HeaderService(getClass().getClassLoader().getResource("soap_header.wsdl"),
+                                            HeaderService.SERVICE);
+        HeaderTester proxy = s.getSoapPortNoRelay();
+        InHeader me = new InHeader();
+        me.setRequestType("CXF user");
+        InHeaderResponse response = null;
+        try {
+            response = proxy.inHeader(me, Constants.IN_HEADER_DATA);
+        } catch (Exception e) {
+            int i = 0;
+        }
+        assertTrue("Expected in in band header *not* to propagate but it did",
+                   response.getResponseType().equals("pass"));
+    }
+    
+    public void testOutHeaderCXFClientNoRelay() throws Exception {
+        HeaderService s = new HeaderService(getClass().getClassLoader().getResource("soap_header.wsdl"),
+                                            HeaderService.SERVICE);
+        HeaderTester proxy = s.getSoapPortNoRelay();
+        OutHeader me = new OutHeader();
+        me.setRequestType("CXF user");
+        Holder<OutHeaderResponse> result = new Holder<OutHeaderResponse>(new OutHeaderResponse());
+        Holder<SOAPHeaderData> header = new Holder<SOAPHeaderData>(new SOAPHeaderData());
+        try {
+            proxy.outHeader(me, result, header);
+        } catch (Exception e) {
+            int i = 0;
+        }
+        assertTrue("Ultimate remote HeaderTester.outHeader() destination was not reached",
+                   result.value.getResponseType().equals("pass"));
+        assertTrue("Expected in band response header *not* to propagate but it did",
+                   header.value == null);
+    }
+    
+    public void testInoutHeaderCXFClientNoRelay() throws Exception {
+        HeaderService s = new HeaderService(getClass().getClassLoader().getResource("soap_header.wsdl"),
+                                            HeaderService.SERVICE);
+        HeaderTester proxy = s.getSoapPortNoRelay();
+        InoutHeader me = new InoutHeader();
+        me.setRequestType("CXF user");
+        Holder<SOAPHeaderData> header = new Holder<SOAPHeaderData>(Constants.IN_OUT_REQUEST_HEADER_DATA);
+        InoutHeaderResponse result = null;
+        try {
+            result = proxy.inoutHeader(me, header);
+        } catch (Exception e) {
+            int i = 0;
+        }
+        assertTrue("Expected in band out header *not* to propagate but it did",
+                   result.getResponseType().equals("pass"));
+        assertTrue("Expected in band response header *not* to propagate but did",
+                   header.value == null);
+    }
+
+    public void testMessageHeadersRelaysSpringContext() throws Exception {
+        CxfEndpoint endpoint = (CxfEndpoint)context.getEndpoint("cxf:bean:serviceExtraRelays");
+        Collection<MessageHeadersRelay> relays = endpoint.getMessageHeadersRelays();
+        assertTrue("Expected 4 relay headers but found " + relays.size(), relays.size() == 3);
+        for (String ns : new CustomHeadersRelay().getActivationNamespaces()) {
+            assertTrue("Expected a CustomHeadersRelay instance to be installed in the endpoint",
+                       endpoint.getMessageHeadersRelay(ns).getClass() == CustomHeadersRelay.class);
+        }
+    }
+    
+    public void testInOutOfBandHeaderCamelTemplateDirect() throws Exception {
+        doTestInOutOfBandHeaderCamelTemplate("direct:directProducer");
+    }
+
+    public void testOutOutOfBandHeaderCamelTemplateDirect() throws Exception {
+        doTestOutOutOfBandHeaderCamelTemplate("direct:directProducer");
+    }
+    
+    public void testInOutOutOfBandHeaderCamelTemplateDirect() throws Exception {
+        doTestInOutOutOfBandHeaderCamelTemplate("direct:directProducer");
+    }
+
+    public void testInOutOfBandHeaderCamelTemplateRelay() throws Exception {
+        doTestInOutOfBandHeaderCamelTemplate("direct:relayProducer");
+    }
+    
+    public void testOutOutOfBandHeaderCamelTemplateRelay() throws Exception {
+        doTestOutOutOfBandHeaderCamelTemplate("direct:relayProducer");
+    }
+
+    public void testInOutOutOfBandHeaderCamelTemplateRelay() throws Exception {
+        doTestInOutOutOfBandHeaderCamelTemplate("direct:relayProducer");
+    }
+
+    
+    protected void doTestInOutOfBandHeaderCamelTemplate(String producerUri) throws Exception {
+        // START SNIPPET: sending
+        Exchange senderExchange = new DefaultExchange(context, ExchangePattern.InOut);
+        final List<Object> params = new ArrayList<Object>();
+        Me me = new Me();
+        me.setFirstName("john");
+        me.setLastName("Doh");
+
+        params.add(me);
+        senderExchange.getIn().setBody(params);
+        senderExchange.getIn().setHeader(CxfConstants.OPERATION_NAME, "inOutOfBandHeader");
+
+        List<Header> headers = buildOutOfBandHeaderList(false);
+        Map<String, Object> requestContext = new HashMap<String, Object>();
+        requestContext.put(Header.HEADER_LIST, headers);
+        senderExchange.getIn().setHeader(Client.REQUEST_CONTEXT, requestContext);
+
+        Exchange exchange = template.send(producerUri, senderExchange);
+
+        org.apache.camel.Message out = exchange.getOut();
+        MessageContentsList result = (MessageContentsList)out.getBody();
+        Map<String, Object> responseContext = CastUtils.cast((Map)out.getHeader(Client.RESPONSE_CONTEXT));
+        assertNotNull(responseContext);
+        assertTrue("Expected the out of band header to propagate but it didn't",
+                   result.get(0) != null && ((Me)result.get(0)).getFirstName().equals("pass"));
+
+    }
+
+    protected void doTestOutOutOfBandHeaderCamelTemplate(String producerUri) throws Exception {
+        // START SNIPPET: sending
+        Exchange senderExchange = new DefaultExchange(context, ExchangePattern.InOut);
+        final List<Object> params = new ArrayList<Object>();
+        Me me = new Me();
+        me.setFirstName("john");
+        me.setLastName("Doh");
+
+        params.add(me);
+        senderExchange.getIn().setBody(params);
+        senderExchange.getIn().setHeader(CxfConstants.OPERATION_NAME, "outOutOfBandHeader");
+
+        Exchange exchange = template.send(producerUri, senderExchange);
+
+        org.apache.camel.Message out = exchange.getOut();
+        MessageContentsList result = (MessageContentsList)out.getBody();
+        assertTrue("Expected the out of band header to propagate but it didn't",
+                   result.get(0) != null && ((Me)result.get(0)).getFirstName().equals("pass"));
+        Map<String, Object> responseContext = CastUtils.cast((Map)out.getHeader(Client.RESPONSE_CONTEXT));
+        assertNotNull(responseContext);
+        validateReturnedOutOfBandHeader(responseContext);
+    }
+
+
+    public void doTestInOutOutOfBandHeaderCamelTemplate(String producerUri) throws Exception {
+        // START SNIPPET: sending
+        Exchange senderExchange = new DefaultExchange(context, ExchangePattern.InOut);
+        final List<Object> params = new ArrayList<Object>();
+        Me me = new Me();
+        me.setFirstName("john");
+        me.setLastName("Doh");
+
+        params.add(me);
+        senderExchange.getIn().setBody(params);
+        senderExchange.getIn().setHeader(CxfConstants.OPERATION_NAME, "inoutOutOfBandHeader");
+
+        List<Header> inHeaders = buildOutOfBandHeaderList(false);
+        Map<String, Object> requestContext = new HashMap<String, Object>();
+        requestContext.put(Header.HEADER_LIST, inHeaders);
+        senderExchange.getIn().setHeader(Client.REQUEST_CONTEXT, requestContext);
+
+        Exchange exchange = template.send(producerUri, senderExchange);
+
+        org.apache.camel.Message out = exchange.getOut();
+        MessageContentsList result = (MessageContentsList)out.getBody();
+        assertTrue("Expected the out of band header to propagate but it didn't",
+                   result.get(0) != null && ((Me)result.get(0)).getFirstName().equals("pass"));
+        Map<String, Object> responseContext = CastUtils.cast((Map)out.getHeader(Client.RESPONSE_CONTEXT));
+        assertNotNull(responseContext);
+        validateReturnedOutOfBandHeader(responseContext);
+    }
+
+    protected static void validateReturnedOutOfBandHeader(HeaderTester proxy) {
+        validateReturnedOutOfBandHeader(proxy, true);
+    }
+    
+    protected static void validateReturnedOutOfBandHeader(HeaderTester proxy, boolean expect) {
+        InvocationHandler handler  = Proxy.getInvocationHandler(proxy);
+        BindingProvider  bp = null;
+        if (!(handler instanceof BindingProvider)) {
+            fail("Unable to cast dynamic proxy InocationHandler to BindingProvider type");
+        }
+
+        bp = (BindingProvider)handler;
+        Map<String, Object> responseContext = bp.getResponseContext();
+        validateReturnedOutOfBandHeader(responseContext, expect);
+    }
+    
+    protected static void validateReturnedOutOfBandHeader(Map<String, Object> responseContext) {
+        validateReturnedOutOfBandHeader(responseContext, true);
+    }
+    
+    protected static void validateReturnedOutOfBandHeader(Map<String, Object> responseContext, boolean expect) {
+        OutofBandHeader hdrToTest = null;
+        List oobHdr = (List)responseContext.get(Header.HEADER_LIST);
+        if (!expect) {
+            if (oobHdr == null || (oobHdr != null && oobHdr.size() == 0)) {
+                return;
+            }
+            fail("Should have got *no* out-of-band headers, but some were found");
+        }
+        if (oobHdr == null) {
+            fail("Should have got List of out-of-band headers");
+        }
+
+        assertTrue("HeaderHolder list expected to conain 1 object received " + oobHdr.size(),
+                   oobHdr.size() == 1);
+
+        if (oobHdr != null & oobHdr instanceof List) {
+            Iterator iter = oobHdr.iterator();
+            while (iter.hasNext()) {
+                Object hdr = iter.next();
+                if (hdr instanceof Header) {
+                    Header hdr1 = (Header)hdr;
+                    if (hdr1.getObject() instanceof Node) {
+                        try {
+                            JAXBElement job = (JAXBElement)JAXBContext
+                                .newInstance(org.apache.cxf.outofband.header.ObjectFactory.class)
+                                .createUnmarshaller().unmarshal((Node)hdr1.getObject());
+                            hdrToTest = (OutofBandHeader)job.getValue();
+                        } catch (JAXBException ex) {
+                            ex.printStackTrace();
+                        }
+                    }
+                }
+            }
+        }
+
+        assertNotNull("out-of-band header should not be null", hdrToTest);
+        assertTrue("Expected out-of-band Header name testOobReturnHeaderName recevied :"
+                   + hdrToTest.getName(), "testOobReturnHeaderName".equals(hdrToTest.getName()));
+        assertTrue("Expected out-of-band Header value testOobReturnHeaderValue recevied :"
+                   + hdrToTest.getValue(), "testOobReturnHeaderValue".equals(hdrToTest.getValue()));
+        assertTrue("Expected out-of-band Header attribute testReturnHdrAttribute recevied :"
+                   + hdrToTest.getHdrAttribute(), "testReturnHdrAttribute"
+            .equals(hdrToTest.getHdrAttribute()));
+    }
+}

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CxfMessageHeadersRelayTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CxfMessageHeadersRelayTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/HeaderTesterImpl.java
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/HeaderTesterImpl.java?rev=756742&view=auto
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/HeaderTesterImpl.java (added)
+++ camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/HeaderTesterImpl.java Fri Mar 20 20:07:40 2009
@@ -0,0 +1,243 @@
+/**
+ * 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.component.cxf.soap.headers;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.annotation.Resource;
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebResult;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.namespace.QName;
+import javax.xml.ws.Holder;
+import javax.xml.ws.WebServiceContext;
+import javax.xml.ws.handler.MessageContext;
+
+import org.w3c.dom.Node;
+
+import org.apache.cxf.headers.Header;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.jaxb.JAXBDataBinding;
+import org.apache.cxf.outofband.header.OutofBandHeader;
+
+
+/**
+ * This class was generated by Apache CXF 2.1.3.4-fuse
+ * Tue Mar 10 17:40:07 GMT-05:00 2009
+ * Generated source version: 2.1.3.4-fuse
+ *
+ */
+
+@javax.jws.WebService(serviceName = "HeaderService",
+                      targetNamespace = "http://apache.org/camel/cxf/soap/headers",
+                      endpointInterface = "org.apache.camel.component.cxf.soap.headers.HeaderTester")
+                      
+public class HeaderTesterImpl implements HeaderTester {
+
+    private static final Logger LOG = Logger.getLogger(HeaderTesterImpl.class.getName());
+    
+    @Resource
+    private WebServiceContext context;
+    private boolean relayHeaders = true;
+    
+    public HeaderTesterImpl() {
+    }
+    
+    public HeaderTesterImpl(boolean relayHeaders) {
+        this.relayHeaders = relayHeaders;
+    }
+    
+    public void outHeader(OutHeader me, Holder<OutHeaderResponse> theResponse, Holder<SOAPHeaderData> headerInfo) {
+        try {
+            OutHeaderResponse theResponseValue = new OutHeaderResponse();
+            theResponseValue.setResponseType("pass");
+            theResponse.value = theResponseValue;
+            headerInfo.value = Constants.OUT_HEADER_DATA;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            throw new RuntimeException(ex);
+        }
+    }
+
+    public InHeaderResponse inHeader(InHeader me, SOAPHeaderData headerInfo) {
+        try {
+            InHeaderResponse result = new InHeaderResponse();
+            if (!relayHeaders) {
+                if (headerInfo == null) {
+                    result.setResponseType("pass");
+                } else {
+                    result.setResponseType("fail");
+                }
+            } else if (Constants.equals(Constants.IN_HEADER_DATA, headerInfo)) {
+                result.setResponseType("pass");
+            } else {
+                result.setResponseType("fail");
+            }
+            return result;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            throw new RuntimeException(ex);
+        }
+    }
+
+    public InoutHeaderResponse inoutHeader(InoutHeader me, Holder<SOAPHeaderData> headerInfo) {
+        try {
+            InoutHeaderResponse result = new InoutHeaderResponse();
+            if (!relayHeaders) {
+                if (headerInfo.value == null) {
+                    result.setResponseType("pass");
+                } else {
+                    result.setResponseType("fail");
+                }
+            } else if (Constants.equals(Constants.IN_OUT_REQUEST_HEADER_DATA, headerInfo.value)) {
+                result.setResponseType("pass");
+            } else {
+                result.setResponseType("fail");
+            }
+            headerInfo.value = Constants.IN_OUT_RESPONSE_HEADER_DATA;
+            return result;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            throw new RuntimeException(ex);
+        }
+    }
+    
+    public Me inOutOfBandHeader(Me me) {
+        try {
+            Me result = new Me();
+            if (validateOutOfBandHander()) {
+                result.setFirstName("pass");
+            } else {
+                result.setFirstName("fail");
+            }
+            return result;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            throw new RuntimeException(ex);
+        }
+    }
+
+    public Me inoutOutOfBandHeader(Me me) {
+        try {
+            Me result = new Me();
+            if (validateOutOfBandHander()) {
+                addReplyOutOfBandHeader();
+                result.setFirstName("pass");
+            } else {
+                result.setFirstName("fail");
+            }
+            return result;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            throw new RuntimeException(ex);
+        }
+    }
+
+    public Me outOutOfBandHeader(Me me) {
+        try {
+            Me result = new Me();
+            result.setFirstName("pass");
+            addReplyOutOfBandHeader();
+            return result;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private void addReplyOutOfBandHeader() {
+        if (context != null) {
+            MessageContext ctx = context.getMessageContext();
+            if (ctx != null) {
+                try {
+                    OutofBandHeader ob = new OutofBandHeader();
+                    ob.setName("testOobReturnHeaderName");
+                    ob.setValue("testOobReturnHeaderValue");
+                    ob.setHdrAttribute("testReturnHdrAttribute");
+                    JAXBElement<OutofBandHeader> job = new JAXBElement<OutofBandHeader>(
+                            new QName(Constants.TEST_HDR_NS, Constants.TEST_HDR_RESPONSE_ELEM),
+                            OutofBandHeader.class, null, ob);
+                    Header hdr = new Header(
+                            new QName(Constants.TEST_HDR_NS, Constants.TEST_HDR_RESPONSE_ELEM),
+                            job,
+                            new JAXBDataBinding(ob.getClass()));
+                    List<Header> hdrList = CastUtils.cast((List<?>) ctx.get(Header.HEADER_LIST));
+                    hdrList.add(hdr);
+                } catch (Exception ex) {
+                    ex.printStackTrace();
+                }
+            }
+        }
+    }
+    
+    private boolean validateOutOfBandHander() {
+        MessageContext ctx = context == null ? null : context.getMessageContext();
+        if (!relayHeaders) {
+            if (ctx != null
+                && !ctx.containsKey(Header.HEADER_LIST)
+                || (ctx.containsKey(Header.HEADER_LIST)
+                    && ((List)ctx.get(Header.HEADER_LIST)).size() == 0)) {
+                return true;
+            }
+            return false;
+        }
+        
+        boolean success = false;
+        if (ctx != null && ctx.containsKey(Header.HEADER_LIST)) {
+            List oobHdr = (List) ctx.get(Header.HEADER_LIST);
+            Iterator iter = oobHdr.iterator();
+            while (iter.hasNext()) {
+                Object hdr = iter.next();
+                if (hdr instanceof Header && ((Header) hdr).getObject() instanceof Node) {
+                    Header hdr1 = (Header) hdr;
+                    try {
+                        JAXBElement job =
+                            (JAXBElement)JAXBContext.newInstance(org.apache.cxf.outofband.header.ObjectFactory.class)
+                                .createUnmarshaller()
+                                .unmarshal((Node) hdr1.getObject());
+                        OutofBandHeader ob = (OutofBandHeader) job.getValue();
+                        if ("testOobHeader".equals(ob.getName())
+                            && "testOobHeaderValue".equals(ob.getValue())) {
+                            if ("testHdrAttribute".equals(ob.getHdrAttribute())) {
+                                success = true;
+                                iter.remove(); //mark it processed
+                            } else if ("dontProcess".equals(ob.getHdrAttribute())) {
+                                //we won't remove it so we won't let the runtime know
+                                //it's processed.   It SHOULD throw an exception
+                                //saying the mustunderstand wasn't processed
+                                success = true;
+                            }
+                        } else {
+                            throw new RuntimeException("test failed");
+                        }
+                    } catch (JAXBException ex) {
+                        ex.printStackTrace();
+                    }
+                }
+            }
+        } else {
+            throw new RuntimeException("MessageContext is null or doesnot contain OOBHeaders");
+        }
+        
+        return success;
+    }    
+}

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/HeaderTesterImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/HeaderTesterImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/branches/camel-1.x/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/spring/message_headers_relay.xml
URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/spring/message_headers_relay.xml?rev=756742&view=auto
==============================================================================
--- camel/branches/camel-1.x/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/spring/message_headers_relay.xml (added)
+++ camel/branches/camel-1.x/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/spring/message_headers_relay.xml Fri Mar 20 20:07:40 2009
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:jaxws="http://cxf.apache.org/jaxws"
+       xmlns:http="http://cxf.apache.org/transports/http/configuration"
+       xmlns:cxf="http://activemq.apache.org/camel/schema/cxfEndpoint"
+       xmlns:camel="http://activemq.apache.org/camel/schema/spring"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
+       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd
+       http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
+       http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
+       http://activemq.apache.org/camel/schema/cxfEndpoint http://activemq.apache.org/camel/schema/cxf/cxfEndpoint.xsd
+       http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd">
+
+  <cxf:cxfEndpoint id="routerRelayEndpoint"
+                   address="http://localhost:9000/HeaderService/"
+                   serviceClass="org.apache.camel.component.cxf.soap.headers.HeaderTester"
+                   endpointName="tns:SoapPortRelay"
+                   serviceName="tns:HeaderService"
+                   wsdlURL="soap_header.wsdl"
+                   xmlns:tns="http://apache.org/camel/component/cxf/soap/headers">
+  </cxf:cxfEndpoint>
+
+  <cxf:cxfEndpoint id="routerNoRelayEndpoint"
+                   address="http://localhost:7000/HeaderService"
+                   serviceClass="org.apache.camel.component.cxf.soap.headers.HeaderTester"
+                   endpointName="tns:SoapPortNoRelay"
+                   serviceName="tns:HeaderService"
+                   wsdlURL="soap_header.wsdl"
+                   xmlns:tns="http://apache.org/camel/component/cxf/soap/headers">
+  </cxf:cxfEndpoint>
+
+
+  <cxf:cxfEndpoint id="serviceRelayEndpoint"
+                   address="http://localhost:9090/HeaderService/"
+                   serviceClass="org.apache.camel.component.cxf.soap.headers.HeaderTester"
+                   endpointName="tns:SoapPortRelay"
+                   serviceName="tns:HeaderService"
+                   wsdlURL="soap_header.wsdl"
+                   xmlns:tns="http://apache.org/camel/component/cxf/soap/headers">
+  </cxf:cxfEndpoint>
+
+  <cxf:cxfEndpoint id="serviceNoRelayEndpoint"
+                   address="http://localhost:7070/HeaderService/"
+                   serviceClass="org.apache.camel.component.cxf.soap.headers.HeaderTester"
+                   endpointName="tns:SoapPortNoRelay"
+                   serviceName="tns:HeaderService"
+                   wsdlURL="soap_header.wsdl"
+                   xmlns:tns="http://apache.org/camel/component/cxf/soap/headers">
+  </cxf:cxfEndpoint>
+  
+  <cxf:cxfEndpoint id="serviceExtraRelays"
+                   address="http://localhost:6060/HeaderService/"
+                   serviceClass="org.apache.camel.component.cxf.soap.headers.HeaderTester"
+                   endpointName="tns:SoapPortCustomRelay"
+                   serviceName="tns:HeaderService"
+                   wsdlURL="soap_header.wsdl"
+                   xmlns:tns="http://apache.org/camel/component/cxf/soap/headers">
+
+      <cxf:properties>
+          <entry key="org.apache.camel.cxf.message.headers.relays">
+           <list>
+           <ref bean="customHeadersRelay"/>
+           </list>
+          </entry>
+      </cxf:properties>
+  </cxf:cxfEndpoint>
+  
+  <bean id="customHeadersRelay" class="org.apache.camel.component.cxf.soap.headers.CustomHeadersRelay"/>
+      
+   <camelContext id="camel" xmlns="http://activemq.apache.org/camel/schema/spring">
+      <route>
+          <from uri="cxf:bean:routerRelayEndpoint"/>
+          <to uri="cxf:bean:serviceRelayEndpoint"/>
+      </route>
+      <route>
+         <from uri="direct:directProducer" />
+         <to uri="cxf:bean:serviceRelayEndpoint?dataFormat=POJO" />
+      </route>
+      <route>
+         <from uri="direct:relayProducer" />
+         <to uri="cxf:bean:routerRelayEndpoint?dataFormat=POJO" />
+      </route>
+      <route>
+          <from uri="cxf:bean:routerNoRelayEndpoint"/>
+          <to uri="cxf:bean:serviceNoRelayEndpoint?relayHeaders=false"/>
+      </route>
+      <route>
+          <from uri="cxf:bean:serviceExtraRelays"/>
+          <to uri="mock:result"/>
+      </route>
+    </camelContext>
+</beans>