You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2019/02/12 12:28:32 UTC

[camel] branch master updated: CAMEL-13116 - DefaultHeaderFilterStrategy match action configurable

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

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


The following commit(s) were added to refs/heads/master by this push:
     new e8805e4  CAMEL-13116 - DefaultHeaderFilterStrategy match action configurable
e8805e4 is described below

commit e8805e4d0760318b7ea2ecafff0fc3607e5551e5
Author: Aniol Massana <an...@corusconsulting.com>
AuthorDate: Fri Feb 8 12:25:03 2019 +0100

    CAMEL-13116 - DefaultHeaderFilterStrategy match action configurable
    
    * filterOnMatch parameter added
    * test cases
    * documentation
---
 .../impl/DefaultHeaderFilterStrategyTest.java      | 29 ++++++-
 .../camel/support/DefaultHeaderFilterStrategy.java | 95 +++++++++++++---------
 ...-avoid-sending-some-or-all-message-headers.adoc | 55 ++++++++++++-
 3 files changed, 133 insertions(+), 46 deletions(-)

diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultHeaderFilterStrategyTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultHeaderFilterStrategyTest.java
index 4bd1333..40d00a0 100644
--- a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultHeaderFilterStrategyTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultHeaderFilterStrategyTest.java
@@ -36,9 +36,12 @@ public class DefaultHeaderFilterStrategyTest extends ContextTestSupport {
 
         comp.setLowerCase(true);
         assertEquals(true, comp.isLowerCase());
-        
+
         comp.setCaseInsensitive(true);
         assertEquals(true, comp.isCaseInsensitive());
+
+        comp.setFilterOnMatch(false);
+        assertEquals(false, comp.isFilterOnMatch());
     }
 
     @Test
@@ -94,12 +97,30 @@ public class DefaultHeaderFilterStrategyTest extends ContextTestSupport {
         assertFalse(comp.applyFilterToCamelHeaders("bar", 123, exchange));
         assertTrue(comp.applyFilterToCamelHeaders("foo", "cheese", exchange));
     }
-    
+
+    @Test
+    public void testOutReverseFilterDefaultHeaderFilterStrategy() {
+        DefaultHeaderFilterStrategy comp = new DefaultHeaderFilterStrategy();
+
+        comp.setFilterOnMatch(false);
+
+        Set<String> set = new HashSet<>();
+        set.add("foo");
+        comp.setOutFilter(set);
+
+        Exchange exchange = new DefaultExchange(context);
+        exchange.getIn().setHeader("bar", 123);
+        exchange.getIn().setHeader("foo", "cheese");
+
+        assertTrue(comp.applyFilterToCamelHeaders("bar", 123, exchange));
+        assertFalse(comp.applyFilterToCamelHeaders("foo", "cheese", exchange));
+    }
+
     @Test
     public void testCaseInsensitiveHeaderNameDoFilterDefaultHeaderFilterStrategy() {
         DefaultHeaderFilterStrategy comp = new DefaultHeaderFilterStrategy();
         comp.setCaseInsensitive(true);
-        
+
         Set<String> set = new HashSet<>();
         set.add("Content-Type");
         comp.setOutFilter(set);
@@ -111,5 +132,5 @@ public class DefaultHeaderFilterStrategyTest extends ContextTestSupport {
         assertTrue(comp.applyFilterToCamelHeaders("content-type", "application/xml", exchange));
         assertTrue(comp.applyFilterToCamelHeaders("Content-Type", "application/json", exchange));
     }
-    
+
 }
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/DefaultHeaderFilterStrategy.java b/core/camel-support/src/main/java/org/apache/camel/support/DefaultHeaderFilterStrategy.java
index 6dbc7cd..d5b29b8 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/DefaultHeaderFilterStrategy.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/DefaultHeaderFilterStrategy.java
@@ -27,18 +27,18 @@ import org.apache.camel.spi.HeaderFilterStrategy;
 /**
  * The default header filtering strategy. Users can configure filter by
  * setting filter set and/or setting a regular expression. Subclass can
- * add extended filter logic in 
+ * add extended filter logic in
  * {@link #extendedFilter(org.apache.camel.spi.HeaderFilterStrategy.Direction, String, Object, org.apache.camel.Exchange)}
- * 
+ *
  * Filters are associated with directions (in or out). "In" direction is
  * referred to propagating headers "to" Camel message. The "out" direction
  * is opposite which is referred to propagating headers from Camel message
  * to a native message like JMS and CXF message. You can see example of
- * DefaultHeaderFilterStrategy are being extended and invoked in camel-jms 
+ * DefaultHeaderFilterStrategy are being extended and invoked in camel-jms
  * and camel-cxf components.
  */
 public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy {
-    
+
     private Set<String> inFilter;
     private Pattern inFilterPattern;
 
@@ -48,7 +48,8 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy {
     private boolean lowerCase;
     private boolean allowNullValues;
     private boolean caseInsensitive;
-    
+    private boolean filterOnMatch = true; // defaults to the previous behaviour
+
     public boolean applyFilterToCamelHeaders(String headerName, Object headerValue, Exchange exchange) {
         return doFiltering(Direction.OUT, headerName, headerValue, exchange);
     }
@@ -60,14 +61,14 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy {
     /**
      * Gets the "out" direction filter set. The "out" direction is referred to
      * copying headers from a Camel message to an external message.
-     * 
+     *
      * @return a set that contains header names that should be excluded.
      */
     public Set<String> getOutFilter() {
         if (outFilter == null) {
             outFilter = new HashSet<>();
         }
-        
+
         return outFilter;
     }
 
@@ -85,8 +86,8 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy {
      * Gets the "out" direction filter regular expression {@link Pattern}. The
      * "out" direction is referred to copying headers from Camel message to
      * an external message. If the pattern matches a header, the header will
-     * be filtered out. 
-     * 
+     * be filtered out.
+     *
      * @return regular expression filter pattern
      */
     public String getOutFilterPattern() {
@@ -97,8 +98,8 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy {
      * Sets the "out" direction filter regular expression {@link Pattern}. The
      * "out" direction is referred to copying headers from Camel message to
      * an external message. If the pattern matches a header, the header will
-     * be filtered out. 
-     * 
+     * be filtered out.
+     *
      * @param value regular expression filter pattern
      */
     public void setOutFilterPattern(String value) {
@@ -108,11 +109,11 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy {
             outFilterPattern = Pattern.compile(value);
         }
     }
-    
+
     /**
      * Gets the "in" direction filter set. The "in" direction is referred to
      * copying headers from an external message to a Camel message.
-     * 
+     *
      * @return a set that contains header names that should be excluded.
      */
     public Set<String> getInFilter() {
@@ -136,20 +137,20 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy {
      * Gets the "in" direction filter regular expression {@link Pattern}. The
      * "in" direction is referred to copying headers from an external message
      * to a Camel message. If the pattern matches a header, the header will
-     * be filtered out. 
-     * 
+     * be filtered out.
+     *
      * @return regular expression filter pattern
      */
     public String getInFilterPattern() {
         return inFilterPattern == null ? null : inFilterPattern.pattern();
     }
-    
+
     /**
      * Sets the "in" direction filter regular expression {@link Pattern}. The
      * "in" direction is referred to copying headers from an external message
      * to a Camel message. If the pattern matches a header, the header will
-     * be filtered out. 
-     * 
+     * be filtered out.
+     *
      * @param value regular expression filter pattern
      */
     public void setInFilterPattern(String value) {
@@ -169,7 +170,7 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy {
     public boolean isLowerCase() {
         return lowerCase;
     }
-    
+
     /**
      * Sets the isLowercase property which is a boolean to determine
      * whether header names should be converted to lower case before
@@ -182,11 +183,11 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy {
 
     /**
      * Gets the caseInsensitive property which is a boolean to determine
-     * whether header names should be case insensitive when checking it 
+     * whether header names should be case insensitive when checking it
      * with the filter set.
      * It does not affect filtering using regular expression pattern.
-     * 
-     * @return <tt>true</tt> if header names is case insensitive. 
+     *
+     * @return <tt>true</tt> if header names is case insensitive.
      */
     public boolean isCaseInsensitive() {
         return caseInsensitive;
@@ -194,66 +195,84 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy {
 
     /**
      * Sets the caseInsensitive property which is a boolean to determine
-     * whether header names should be case insensitive when checking it 
+     * whether header names should be case insensitive when checking it
      * with the filter set.
      * It does not affect filtering using regular expression pattern,
-     * 
+     *
      * @param caseInsensitive <tt>true</tt> if header names is case insensitive.
      */
     public void setCaseInsensitive(boolean caseInsensitive) {
         this.caseInsensitive = caseInsensitive;
     }
-    
+
     public boolean isAllowNullValues() {
         return allowNullValues;
     }
-    
+
     public void setAllowNullValues(boolean value) {
         allowNullValues = value;
-    }   
+    }
+
+    public boolean isFilterOnMatch() {
+        return filterOnMatch;
+    }
+
+    /**
+     * Sets the filterOnMatch property which is a boolean to determine
+     * what to do when a pattern or filter set is matched.
+     *
+     * When set to true, a match will filter out the header. This is the default value for backwards compatibility.
+     *
+     * When set to false, the pattern or filter will indicate that the header must be kept; anything not matched will be filtered out.
+     *
+     * @param filterOnMatch <tt>true</tt> if a match filters out the header.
+     */
+    public void setFilterOnMatch(boolean filterOnMatch) {
+        this.filterOnMatch = filterOnMatch;
+    }
 
     protected boolean extendedFilter(Direction direction, String key, Object value, Exchange exchange) {
-        return false;
+        return !filterOnMatch;
     }
 
     private boolean doFiltering(Direction direction, String headerName, Object headerValue, Exchange exchange) {
         if (headerName == null) {
             return true;
         }
-        
+
         if (headerValue == null && !allowNullValues) {
             return true;
         }
-        
+
         Pattern pattern = null;
         Set<String> filter = null;
-        
+
         if (Direction.OUT == direction) {
             pattern = outFilterPattern;
-            filter = outFilter;                
+            filter = outFilter;
         } else if (Direction.IN == direction) {
             pattern = inFilterPattern;
             filter = inFilter;
         }
-   
+
         if (pattern != null && pattern.matcher(headerName).matches()) {
-            return true;
+            return filterOnMatch;
         }
-            
+
         if (filter != null) {
             if (isCaseInsensitive()) {
                 for (String filterString : filter) {
                     if (filterString.equalsIgnoreCase(headerName)) {
-                        return true;
+                        return filterOnMatch;
                     }
                 }
             } else if (isLowerCase()) {
                 if (filter.contains(headerName.toLowerCase(Locale.ENGLISH))) {
-                    return true;
+                    return filterOnMatch;
                 }
             } else {
                 if (filter.contains(headerName)) {
-                    return true;
+                    return filterOnMatch;
                 }
             }
         }
diff --git a/docs/user-manual/en/faq/how-to-avoid-sending-some-or-all-message-headers.adoc b/docs/user-manual/en/faq/how-to-avoid-sending-some-or-all-message-headers.adoc
index be9f6b4..6a3e156 100644
--- a/docs/user-manual/en/faq/how-to-avoid-sending-some-or-all-message-headers.adoc
+++ b/docs/user-manual/en/faq/how-to-avoid-sending-some-or-all-message-headers.adoc
@@ -69,7 +69,54 @@ An alternative is that some of the Camel
 link:../component.adoc[Components] supports configuring a custom header
 filter strategy.
 This allows you to implement the
-`org.apache.camel.spi.HeaderFilterStrategy` interface, where you can
-filter unwanted headers.
-Though it's often easier to use the `removeHeaders` in the Camel route as
-shown above.
+`org.apache.camel.spi.HeaderFilterStrategy` interface, where one can
+filter unwanted headers from the communication while not removing them from the
+Exchange. Though it's often easier to use the `removeHeaders` in the Camel route
+as shown above.
+
+Camel core offers a default filter strategy implementation, the
+DefaultHeaderFilterStrategy class, to which one can provide a regular expression
+pattern or a set of header names to be filtered out.
+
+[source,xml]
+----
+<bean class="org.apache.camel.impl.DefaultHeaderFilterStrategy" id="myFilter">
+    <property name="outFilter">
+        <set>
+            <value>unwantedHeaderName</value>
+        </set>
+    </property>
+</bean>
+...
+<setHeader headerName="allowedHeaderName"><constant>some metadata</constant></setHeader>
+<setHeader headerName="unwantedHeaderName"><constant>some private data</constant></setHeader>
+<to id="publish" uri="activemq:queue:destinationName?headerFilterStrategy=#myFilter"/>
+<log message="${header.unwantedHeaderName}"/>
+----
+
+The destination queue would receive a JMS message with the allowedHeaderName as
+JMS property. If the queue messages are consumed by a Camel route, then the
+exchange will have the allowedHeaderName as a header. The log would print "some
+private data" since the header has only been filtered out from the producer
+endpoint, but not removed from the Exchange.
+
+[[Howtoavoidsendingsomeorallmessageheaders-SelectingTheAcceptedHeaders]]
+==== Selecting the accepted headers
+
+The more steps a route has, more headers tend to be present in the exchange.
+When the number of headers is large, undetermined, or one can't know in advance
+which headers must be filtered out, it is desirable not to deliver by default
+the headers to the destination endpoint.
+
+In this case, one can filter out everything and selectively send only certain
+headers to the destination endpoint. The DefaultHeaderFilterStrategy behavior
+can be reversed so only certain headers are accepted through the filterOnMatch
+property.
+
+[source,xml]
+----
+<bean class="org.apache.camel.impl.DefaultHeaderFilterStrategy" id="myFilter">
+    <property name="filterOnMatch" value="false" />
+    ...
+</bean>
+----