001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.impl;
018    
019    import java.util.HashSet;
020    import java.util.Set;
021    import java.util.regex.Pattern;
022    
023    import org.apache.camel.spi.HeaderFilterStrategy;
024    
025    /**
026     * The default header filtering strategy.  Users can configure filter by 
027     * setting filter set and/or setting a regular expression.  Subclass can 
028     * add extended filter logic in 
029     * {@link #extendedFilter(org.apache.camel.impl.DefaultHeaderFilterStrategy.Direction, String, Object)}
030     * 
031     * Filters are associated with directions (in or out).  "In" direction is 
032     * referred to propagating headers "to" Camel message.  The "out" direction
033     * is opposite which is referred to propagating headers from Camel message
034     * to a native message like JMS and CXF message.  You can see example of
035     * DefaultHeaderFilterStrategy are being extended and invoked in camel-jms 
036     * and camel-cxf components.
037     *
038     * @version $Revision: 747062 $
039     */
040    public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy {
041    
042        protected enum Direction { IN, OUT }
043        
044        private Set<String> inFilter;
045        private Pattern inFilterPattern;
046    
047        private Set<String> outFilter;
048        private Pattern outFilterPattern;
049    
050        private boolean lowerCase;
051        private boolean allowNullValues;
052        
053        public boolean applyFilterToCamelHeaders(String headerName, Object headerValue) {
054            return doFiltering(Direction.OUT, headerName, headerValue);
055        }
056    
057        public boolean applyFilterToExternalHeaders(String headerName, Object headerValue) {
058            return doFiltering(Direction.IN, headerName, headerValue);
059        }
060    
061        /**
062         * Gets the "out" direction filter set.  The "out" direction is referred to 
063         * copying headers from a Camel message to an external message.
064         * 
065         * @return a set that contains header names that should be excluded.
066         */
067        public Set<String> getOutFilter() {
068            if (outFilter == null) {
069                outFilter = new HashSet<String>();
070            }
071            
072            return outFilter;
073        }
074    
075        /**
076         * Sets the "out" direction filter set.  The "out" direction is referred to 
077         * copying headers from a Camel message to an external message.
078         *
079         * @param value  the filter
080         */
081        public void setOutFilter(Set<String> value) {
082            outFilter = value;
083        }
084    
085        /**
086         * Gets the "out" direction filter regular expression {@link Pattern}.  The
087         * "out" direction is referred to copying headers from Camel message to
088         * an external message.  If the pattern matches a header, the header will 
089         * be filtered out. 
090         * 
091         * @return regular expression filter pattern
092         */
093        public String getOutFilterPattern() {
094            return outFilterPattern == null ? null : outFilterPattern.pattern();
095        }
096        
097    
098        /**
099         * Sets the "out" direction filter regular expression {@link Pattern}.  The
100         * "out" direction is referred to copying headers from Camel message to
101         * an external message.  If the pattern matches a header, the header will 
102         * be filtered out. 
103         * 
104         * @param value regular expression filter pattern
105         */
106        public void setOutFilterPattern(String value) {
107            if (value == null) {
108                outFilterPattern = null;
109            } else {
110                outFilterPattern = Pattern.compile(value);
111            }
112        }
113        
114        /**
115         * Gets the "in" direction filter set.  The "in" direction is referred to 
116         * copying headers from an external message to a Camel message.
117         * 
118         * @return a set that contains header names that should be excluded.
119         */
120        public Set<String> getInFilter() {
121            if (inFilter == null) {
122                inFilter = new HashSet<String>();
123            }
124            return inFilter;
125        }
126    
127        /**
128         * Sets the "in" direction filter set.  The "in" direction is referred to 
129         * copying headers from an external message to a Camel message.
130         *
131         * @param value the filter
132         */
133        public void setInFilter(Set<String> value) {
134            inFilter = value;
135        }
136    
137        /**
138         * Gets the "in" direction filter regular expression {@link Pattern}.  The
139         * "in" direction is referred to copying headers from an external message
140         * to a Camel message.  If the pattern matches a header, the header will 
141         * be filtered out. 
142         * 
143         * @return regular expression filter pattern
144         */
145        public String getInFilterPattern() {
146            return inFilterPattern == null ? null : inFilterPattern.pattern();
147        }
148        
149        /**
150         * Sets the "in" direction filter regular expression {@link Pattern}.  The
151         * "in" direction is referred to copying headers from an external message
152         * to a Camel message.  If the pattern matches a header, the header will 
153         * be filtered out. 
154         * 
155         * @param value regular expression filter pattern
156         */
157        public void setInFilterPattern(String value) {
158            if (value == null) {
159                inFilterPattern = null;
160            } else {
161                inFilterPattern = Pattern.compile(value);
162            }
163        }
164    
165        /**
166         * Gets the isLowercase property which is a boolean to determinte
167         * whether header names should be converted to lowercase before
168         * checking it the filter Set.  It does not affect filtering using
169         * regular expression pattern.
170         */
171        public boolean isLowerCase() {
172            return lowerCase;
173        }
174        
175        /**
176         * Sets the isLowercase property which is a boolean to determinte
177         * whether header names should be converted to lowercase before
178         * checking it the filter Set.  It does not affect filtering using
179         * regular expression pattern.
180         */
181        public void setLowerCase(boolean value) {
182            lowerCase = value;
183        }
184        
185        public boolean getAllowNullValues() {
186            return allowNullValues;
187        }
188        
189        public void setAllowNullValues(boolean value) {
190            allowNullValues = value;
191        }   
192    
193        protected boolean extendedFilter(Direction direction, String key, Object value) {
194            return false;
195        }
196    
197        private boolean doFiltering(Direction direction, String headerName, Object headerValue) {
198            if (headerName == null) {
199                return true;
200            }
201            
202            if (headerValue == null && !allowNullValues) {
203                return true;
204            }
205            
206            Pattern pattern = null;
207            Set<String> filter = null;
208            
209            if (Direction.OUT == direction) {
210                pattern = outFilterPattern;
211                filter = outFilter;                
212            } else if (Direction.IN == direction) {
213                pattern = inFilterPattern;
214                filter = inFilter;
215            }
216       
217            if (pattern != null && pattern.matcher(headerName).matches()) {
218                return true;
219            }
220                
221            if (filter != null) {
222                if (isLowerCase()) {
223                    if (filter.contains(headerName.toLowerCase())) {
224                        return true;
225                    }
226                } else {
227                    if (filter.contains(headerName)) {
228                        return true;
229                    }
230                }
231            }
232                
233            if (extendedFilter(direction, headerName, headerValue)) {
234                return true;
235            }
236                
237            return false;
238        }
239    }