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: 45301 $
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 isLowercase;
051 private boolean allowNullValues;
052
053 /**
054 * Applies filtering logic to Camel Message header that is
055 * going to be copied to target message.
056 *
057 * It returns true if the filtering logics return a match. Otherwise,
058 * it returns false. A match means the header should be excluded.
059 *
060 * @param headerName
061 * @param headerValue
062 * @return true if this header should be filtered out.
063 */
064 public boolean applyFilterToCamelHeaders(String headerName, Object headerValue) {
065 return doFiltering(Direction.OUT, headerName, headerValue);
066 }
067
068 /**
069 * Applies filtering logic to an external message header message that
070 * is going to be copied to Camel message header.
071 *
072 * It returns true if the filtering logics return a match. Otherwise,
073 * it returns false. A match means the header should be excluded.
074 *
075 * @param headerName
076 * @param headerValue
077 * @return true if this header should be excluded.
078 */
079 public boolean applyFilterToExternalHeaders(String headerName, Object headerValue) {
080 return doFiltering(Direction.IN, headerName, headerValue);
081 }
082
083 /**
084 * Gets the "out" direction filter set. The "out" direction is referred to
085 * copying headers from a Camel message to an external message.
086 *
087 * @return a set that contains header names that should be excluded.
088 */
089 public Set<String> getOutFilter() {
090 if (outFilter == null) {
091 outFilter = new HashSet<String>();
092 }
093
094 return outFilter;
095 }
096
097 /**
098 * Sets the "out" direction filter set. The "out" direction is referred to
099 * copying headers from a Camel message to an external message.
100 *
101 * @return a set that contains headers names that should be excluded.
102 */
103 public void setOutFilter(Set<String> value) {
104 outFilter = value;
105 }
106
107 /**
108 * Gets the "out" direction filter regular expression {@link Pattern}. The
109 * "out" direction is referred to copying headers from Camel message to
110 * an external message. If the pattern matches a header, the header will
111 * be filtered out.
112 *
113 * @return regular expression filter pattern
114 */
115 public String getOutFilterPattern() {
116 return outFilterPattern == null ? null : outFilterPattern.pattern();
117 }
118
119
120 /**
121 * Sets the "out" direction filter regular expression {@link Pattern}. The
122 * "out" direction is referred to copying headers from Camel message to
123 * an external message. If the pattern matches a header, the header will
124 * be filtered out.
125 *
126 * @param value regular expression filter pattern
127 */
128 public void setOutFilterPattern(String value) {
129 if (value == null) {
130 outFilterPattern = null;
131 } else {
132 outFilterPattern = Pattern.compile(value);
133 }
134 }
135
136 /**
137 * Gets the "in" direction filter set. The "in" direction is referred to
138 * copying headers from an external message to a Camel message.
139 *
140 * @return a set that contains header names that should be excluded.
141 */
142 public Set<String> getInFilter() {
143 if (inFilter == null) {
144 inFilter = new HashSet<String>();
145 }
146 return inFilter;
147 }
148
149 /**
150 * Sets the "in" direction filter set. The "in" direction is referred to
151 * copying headers from an external message to a Camel message.
152 *
153 * @return a set that contains headers names that should be excluded.
154 */
155 public void setInFilter(Set<String> value) {
156 inFilter = value;
157 }
158
159 /**
160 * Gets the "in" direction filter regular expression {@link Pattern}. The
161 * "in" direction is referred to copying headers from an external message
162 * to a Camel message. If the pattern matches a header, the header will
163 * be filtered out.
164 *
165 * @return regular expression filter pattern
166 */
167 public String getInFilterPattern() {
168 return inFilterPattern == null ? null : inFilterPattern.pattern();
169 }
170
171 /**
172 * Sets the "in" direction filter regular expression {@link Pattern}. The
173 * "in" direction is referred to copying headers from an external message
174 * to a Camel message. If the pattern matches a header, the header will
175 * be filtered out.
176 *
177 * @param value regular expression filter pattern
178 */
179 public void setInFilterPattern(String value) {
180 if (value == null) {
181 inFilterPattern = null;
182 } else {
183 inFilterPattern = Pattern.compile(value);
184 }
185 }
186
187 /**
188 * Gets the isLowercase property which is a boolean to determinte
189 * whether header names should be converted to lowercase before
190 * checking it the filter Set. It does not affect filtering using
191 * regular expression pattern.
192 */
193 public boolean getIsLowercase() {
194 return isLowercase;
195 }
196
197 /**
198 * Sets the isLowercase property which is a boolean to determinte
199 * whether header names should be converted to lowercase before
200 * checking it the filter Set. It does not affect filtering using
201 * regular expression pattern.
202 */
203 public void setIsLowercase(boolean value) {
204 isLowercase = value;
205 }
206
207 public boolean getAllowNullValues() {
208 return allowNullValues;
209 }
210
211 public void setAllowNullValues(boolean value) {
212 allowNullValues = value;
213 }
214
215 protected boolean extendedFilter(Direction direction, String key, Object value) {
216 return false;
217 }
218
219 private boolean doFiltering(Direction direction, String headerName, Object headerValue) {
220
221 if (headerName == null) {
222 return true;
223 }
224
225 if (headerValue == null && !allowNullValues) {
226 return true;
227 }
228
229 Pattern pattern = null;
230 Set<String> filter = null;
231
232 if (Direction.OUT == direction) {
233 pattern = outFilterPattern;
234 filter = outFilter;
235 } else if (Direction.IN == direction) {
236 pattern = inFilterPattern;
237 filter = inFilter;
238 }
239
240 if (pattern != null && pattern.matcher(headerName).matches()) {
241 return true;
242 }
243
244 if (filter != null) {
245 if (isLowercase) {
246 if (filter.contains(headerName.toLowerCase())) {
247 return true;
248 }
249 } else {
250 if (filter.contains(headerName)) {
251 return true;
252 }
253 }
254 }
255
256 if (extendedFilter(direction, headerName, headerValue)) {
257 return true;
258 }
259
260 return false;
261 }
262 }