blob: 6d4edd05af4bb67c87c7f21455d2a24d3a1cd094 [file] [log] [blame]
/**
* 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.common.header;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.camel.Exchange;
import org.apache.camel.component.cxf.common.message.CxfConstants;
import org.apache.camel.impl.DefaultHeaderFilterStrategy;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.headers.Header;
import org.apache.cxf.message.Message;
import org.apache.cxf.service.model.BindingInfo;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The default CXF header filter strategy.
*
* @version
*/
public class CxfHeaderFilterStrategy extends DefaultHeaderFilterStrategy {
private static final Logger LOG = LoggerFactory.getLogger(CxfHeaderFilterStrategy.class);
private Map<String, MessageHeaderFilter> messageHeaderFiltersMap;
private List<MessageHeaderFilter> messageHeaderFilters;
private boolean relayHeaders = true;
private boolean allowFilterNamespaceClash;
private boolean relayAllMessageHeaders;
public CxfHeaderFilterStrategy() {
initialize();
}
protected void initialize() {
//filter the operationName and operationName
getOutFilter().add(CxfConstants.OPERATION_NAME.toLowerCase());
getOutFilter().add(CxfConstants.OPERATION_NAMESPACE.toLowerCase());
// Request and response context Maps will be passed to CXF Client APIs
getOutFilter().add(Client.REQUEST_CONTEXT.toLowerCase());
getOutFilter().add(Client.RESPONSE_CONTEXT.toLowerCase());
// protocol headers are stored as a Map. DefaultCxfBinding
// read the Map and send each entry to the filter. Therefore,
// we need to filter the header of this name.
getOutFilter().add(Message.PROTOCOL_HEADERS.toLowerCase());
getInFilter().add(Message.PROTOCOL_HEADERS.toLowerCase());
// Add the filter for the Generic Message header
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.5
getOutFilter().add("cache-control");
getOutFilter().add("connection");
getOutFilter().add("date");
getOutFilter().add("pragma");
getOutFilter().add("trailer");
getOutFilter().add("transfer-encoding");
getOutFilter().add("upgrade");
getOutFilter().add("via");
getOutFilter().add("warning");
// Since CXF can take the content-type from the protocol header
// we need to filter this header of this name.
getOutFilter().add("Content-Type".toLowerCase());
// Filter out Content-Length since it can fool Jetty (HttpGenerator) to
// close response output stream prematurely. (It occurs when the
// message size (e.g. with attachment) is large and response content length
// is bigger than request content length.)
getOutFilter().add("Content-Length".toLowerCase());
// Filter Content-Length as it will cause some trouble when the message
// is passed to the other endpoint
getInFilter().add("content-length".toLowerCase());
setLowerCase(true);
// initialize message header filter map with default SOAP filter
messageHeaderFiltersMap = new HashMap<String, MessageHeaderFilter>();
addToMessageHeaderFilterMap(new SoapMessageHeaderFilter());
// filter headers begin with "Camel" or "org.apache.camel"
setOutFilterPattern("(Camel|org\\.apache\\.camel)[\\.|a-z|A-z|0-9]*");
}
@SuppressWarnings("unchecked")
@Override
protected boolean extendedFilter(Direction direction, String key, Object value, Exchange exchange) {
// Currently only handles Header.HEADER_LIST message header relay/filter
if (!Header.HEADER_LIST.equals(key) || value == null) {
return false;
}
if (!relayHeaders) {
// not propagating Header.HEADER_LIST at all
return true;
}
if (relayAllMessageHeaders) {
// all message headers will be relayed (no filtering)
return false;
}
// get filter
MessageHeaderFilter messageHeaderfilter = getMessageHeaderFilter(exchange);
if (messageHeaderfilter == null) {
LOG.debug("No CXF Binding namespace can be resolved. Message headers are intact.");
return false;
}
LOG.trace("messageHeaderfilter = {}", messageHeaderfilter);
try {
messageHeaderfilter.filter(direction, (List<Header>)value);
} catch (Throwable t) {
if (LOG.isDebugEnabled()) {
LOG.debug("Failed to cast value to Header<List> due to " + t.toString(), t);
}
}
// return false since the header list (which has been filtered) should be propagated
return false;
}
private void addToMessageHeaderFilterMap(MessageHeaderFilter filter) {
for (String ns : filter.getActivationNamespaces()) {
if (messageHeaderFiltersMap.containsKey(ns) && messageHeaderFiltersMap.get(ns)
!= messageHeaderFiltersMap && !allowFilterNamespaceClash) {
throw new IllegalArgumentException("More then one MessageHeaderRelay activates "
+ "for the same namespace: " + ns);
}
messageHeaderFiltersMap.put(ns, filter);
}
}
private MessageHeaderFilter getMessageHeaderFilter(Exchange exchange) {
BindingOperationInfo boi = exchange.getProperty(BindingOperationInfo.class.getName(),
BindingOperationInfo.class);
String ns = null;
if (boi != null) {
BindingInfo b = boi.getBinding();
if (b != null) {
ns = b.getBindingId();
}
}
MessageHeaderFilter answer = null;
if (ns != null) {
answer = messageHeaderFiltersMap.get(ns);
}
return answer;
}
/**
* @param messageHeaderFilters the messageHeaderFilters to set
*/
public void setMessageHeaderFilters(List<MessageHeaderFilter> messageHeaderFilters) {
this.messageHeaderFilters = messageHeaderFilters;
// clear the amp to allow removal of default filter
messageHeaderFiltersMap.clear();
for (MessageHeaderFilter filter : messageHeaderFilters) {
addToMessageHeaderFilterMap(filter);
}
}
/**
* @return the messageHeaderFilters
*/
public List<MessageHeaderFilter> getMessageHeaderFilters() {
return messageHeaderFilters;
}
/**
* @return the allowFilterNamespaceClash
*/
public boolean isAllowFilterNamespaceClash() {
return allowFilterNamespaceClash;
}
/**
* @param allowFilterNamespaceClash the allowFilterNamespaceClash to set
*/
public void setAllowFilterNamespaceClash(boolean allowFilterNamespaceClash) {
this.allowFilterNamespaceClash = allowFilterNamespaceClash;
}
/**
* @return the messageHeaderFiltersMap
*/
public Map<String, MessageHeaderFilter> getMessageHeaderFiltersMap() {
return messageHeaderFiltersMap;
}
/**
* @param relayHeaders the relayHeaders to set
*/
public void setRelayHeaders(boolean relayHeaders) {
this.relayHeaders = relayHeaders;
}
/**
* @return the relayHeaders
*/
public boolean isRelayHeaders() {
return relayHeaders;
}
/**
* @return the relayAllMessageHeaders
*/
public boolean isRelayAllMessageHeaders() {
return relayAllMessageHeaders;
}
/**
* @param relayAllMessageHeaders the relayAllMessageHeaders to set
*/
public void setRelayAllMessageHeaders(boolean relayAllMessageHeaders) {
this.relayAllMessageHeaders = relayAllMessageHeaders;
}
}