KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > web > filter > GenericFilterBean


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.web.filter;
18
19 import java.util.Enumeration JavaDoc;
20 import java.util.HashSet JavaDoc;
21 import java.util.Set JavaDoc;
22
23 import javax.servlet.Filter JavaDoc;
24 import javax.servlet.FilterConfig JavaDoc;
25 import javax.servlet.ServletContext JavaDoc;
26 import javax.servlet.ServletException JavaDoc;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import org.springframework.beans.BeanWrapper;
32 import org.springframework.beans.BeanWrapperImpl;
33 import org.springframework.beans.BeansException;
34 import org.springframework.beans.MutablePropertyValues;
35 import org.springframework.beans.PropertyValue;
36 import org.springframework.beans.PropertyValues;
37 import org.springframework.beans.factory.BeanInitializationException;
38 import org.springframework.beans.factory.BeanNameAware;
39 import org.springframework.beans.factory.DisposableBean;
40 import org.springframework.beans.factory.InitializingBean;
41 import org.springframework.core.io.Resource;
42 import org.springframework.core.io.ResourceEditor;
43 import org.springframework.core.io.ResourceLoader;
44 import org.springframework.util.Assert;
45 import org.springframework.util.StringUtils;
46 import org.springframework.web.context.ServletContextAware;
47 import org.springframework.web.context.support.ServletContextResourceLoader;
48 import org.springframework.web.util.NestedServletException;
49
50 /**
51  * Simple base implementation of {@link javax.servlet.Filter} which treats
52  * its config parameters as bean properties. Unknown parameters are ignored.
53  *
54  * <p>A very handy superclass for any type of filter. Type conversion of
55  * config parameters is automatic. It is also possible for subclasses to
56  * specify required properties.
57  *
58  * <p>This filter leaves actual filtering to subclasses, which have to
59  * implement the {@link javax.servlet.Filter#doFilter} method.
60  *
61  * <p>This filter superclass has no dependency on a Spring application context.
62  * Filters usually don't load their own context but rather access beans from
63  * the root application context, accessible via the ServletContext.
64  *
65  * @author Juergen Hoeller
66  * @since 06.12.2003
67  * @see #addRequiredProperty
68  * @see #initFilterBean
69  * @see #doFilter
70  * @see org.springframework.web.context.support.WebApplicationContextUtils#getWebApplicationContext
71  */

72 public abstract class GenericFilterBean implements
73         Filter JavaDoc, BeanNameAware, ServletContextAware, InitializingBean, DisposableBean {
74
75     /** Logger available to subclasses */
76     protected final Log logger = LogFactory.getLog(getClass());
77
78     /**
79      * Set of required properties (Strings) that must be supplied as
80      * config parameters to this filter.
81      */

82     private final Set JavaDoc requiredProperties = new HashSet JavaDoc();
83
84     /* The FilterConfig of this filter */
85     private FilterConfig JavaDoc filterConfig;
86
87
88     private String JavaDoc beanName;
89
90     private ServletContext JavaDoc servletContext;
91
92
93     /**
94      * Stores the bean name as defined in the Spring bean factory.
95      * <p>Only relevant in case of initialization as bean, to have a name as
96      * fallback to the filter name usually provided by a FilterConfig instance.
97      * @see org.springframework.beans.factory.BeanNameAware
98      * @see #getFilterName()
99      */

100     public final void setBeanName(String JavaDoc beanName) {
101         this.beanName = beanName;
102     }
103
104     /**
105      * Stores the ServletContext that the bean factory runs in.
106      * <p>Only relevant in case of initialization as bean, to have a ServletContext
107      * as fallback to the context usually provided by a FilterConfig instance.
108      * @see org.springframework.web.context.ServletContextAware
109      * @see #getServletContext()
110      */

111     public final void setServletContext(ServletContext JavaDoc servletContext) {
112         this.servletContext = servletContext;
113     }
114
115     /**
116      * Calls the <code>initFilterBean()</code> method that might
117      * contain custom initialization of a subclass.
118      * <p>Only relevant in case of initialization as bean, where the
119      * standard <code>init(FilterConfig)</code> method won't be called.
120      * @see #initFilterBean()
121      * @see #init(javax.servlet.FilterConfig)
122      */

123     public void afterPropertiesSet() throws ServletException JavaDoc {
124         initFilterBean();
125     }
126
127
128     /**
129      * Subclasses can invoke this method to specify that this property
130      * (which must match a JavaBean property they expose) is mandatory,
131      * and must be supplied as a config parameter. This should be called
132      * from the constructor of a subclass.
133      * <p>This method is only relevant in case of traditional initialization
134      * driven by a FilterConfig instance.
135      * @param property name of the required property
136      */

137     protected final void addRequiredProperty(String JavaDoc property) {
138         this.requiredProperties.add(property);
139     }
140
141     /**
142      * Standard way of initializing this filter.
143      * Map config parameters onto bean properties of this filter, and
144      * invoke subclass initialization.
145      * @param filterConfig the configuration for this filter
146      * @throws ServletException if bean properties are invalid (or required
147      * properties are missing), or if subclass initialization fails.
148      * @see #initFilterBean
149      */

150     public final void init(FilterConfig JavaDoc filterConfig) throws ServletException JavaDoc {
151         Assert.notNull(filterConfig, "FilterConfig must not be null");
152         if (logger.isDebugEnabled()) {
153             logger.debug("Initializing filter '" + filterConfig.getFilterName() + "'");
154         }
155
156         this.filterConfig = filterConfig;
157
158         // Set bean properties from init parameters.
159
try {
160             PropertyValues pvs = new FilterConfigPropertyValues(filterConfig, this.requiredProperties);
161             BeanWrapper bw = new BeanWrapperImpl(this);
162             ResourceLoader resourceLoader = new ServletContextResourceLoader(filterConfig.getServletContext());
163             bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader));
164             initBeanWrapper(bw);
165             bw.setPropertyValues(pvs, true);
166         }
167         catch (BeansException ex) {
168             String JavaDoc msg = "Failed to set bean properties on filter '" +
169                 filterConfig.getFilterName() + "': " + ex.getMessage();
170             logger.error(msg, ex);
171             throw new NestedServletException(msg, ex);
172         }
173
174         // Let subclasses do whatever initialization they like.
175
initFilterBean();
176
177         if (logger.isDebugEnabled()) {
178             logger.debug("Filter '" + filterConfig.getFilterName() + "' configured successfully");
179         }
180     }
181
182     /**
183      * Alternative way of initializing this filter.
184      * Used by Servlet Filter version that shipped with WebLogic 6.1.
185      * @param filterConfig the configuration for this filter
186      * @throws BeanInitializationException wrapping a ServletException
187      * thrown by the <code>init</code> method
188      * @deprecated as of Spring 2.0; to be removed in Spring 2.1
189      * @see #init(javax.servlet.FilterConfig)
190      */

191     public final void setFilterConfig(FilterConfig JavaDoc filterConfig) {
192         try {
193             init(filterConfig);
194         }
195         catch (ServletException JavaDoc ex) {
196             throw new BeanInitializationException("Could not initialize filter bean", ex);
197         }
198     }
199
200     /**
201      * Initialize the BeanWrapper for this GenericFilterBean,
202      * possibly with custom editors.
203      * <p>This default implementation is empty.
204      * @param bw the BeanWrapper to initialize
205      * @throws BeansException if thrown by BeanWrapper methods
206      * @see org.springframework.beans.BeanWrapper#registerCustomEditor
207      */

208     protected void initBeanWrapper(BeanWrapper bw) throws BeansException {
209     }
210
211
212     /**
213      * Make the FilterConfig of this filter available, if any.
214      * Analogous to GenericServlet's <code>getServletConfig()</code>.
215      * <p>Public to resemble the <code>getFilterConfig()</code> method
216      * of the Servlet Filter version that shipped with WebLogic 6.1.
217      * @return the FilterConfig instance, or <code>null</code> if none available
218      * @see javax.servlet.GenericServlet#getServletConfig()
219      */

220     public final FilterConfig JavaDoc getFilterConfig() {
221         return this.filterConfig;
222     }
223
224     /**
225      * Make the name of this filter available to subclasses.
226      * Analogous to GenericServlet's <code>getServletName()</code>.
227      * <p>Takes the FilterConfig's filter name by default.
228      * If initialized as bean in a Spring application context,
229      * it falls back to the bean name as defined in the bean factory.
230      * @return the filter name, or <code>null</code> if none available
231      * @see javax.servlet.GenericServlet#getServletName()
232      * @see javax.servlet.FilterConfig#getFilterName()
233      * @see #setBeanName
234      */

235     protected final String JavaDoc getFilterName() {
236         return (this.filterConfig != null ? this.filterConfig.getFilterName() : this.beanName);
237     }
238
239     /**
240      * Make the ServletContext of this filter available to subclasses.
241      * Analogous to GenericServlet's <code>getServletContext()</code>.
242      * <p>Takes the FilterConfig's ServletContext by default.
243      * If initialized as bean in a Spring application context,
244      * it falls back to the ServletContext that the bean factory runs in.
245      * @return the ServletContext instance, or <code>null</code> if none available
246      * @see javax.servlet.GenericServlet#getServletContext()
247      * @see javax.servlet.FilterConfig#getServletContext()
248      * @see #setServletContext
249      */

250     protected final ServletContext JavaDoc getServletContext() {
251         return (this.filterConfig != null ? this.filterConfig.getServletContext() : this.servletContext);
252     }
253
254
255     /**
256      * Subclasses may override this to perform custom initialization.
257      * All bean properties of this filter will have been set before this
258      * method is invoked.
259      * <p>Note: This method will be called from standard filter initialization
260      * as well as filter bean initialization in a Spring application context.
261      * Filter name and ServletContext will be available in both cases.
262      * <p>This default implementation is empty.
263      * @throws ServletException if subclass initialization fails
264      * @see #getFilterName()
265      * @see #getServletContext()
266      */

267     protected void initFilterBean() throws ServletException JavaDoc {
268     }
269
270     /**
271      * Subclasses may override this to perform custom filter shutdown.
272      * <p>Note: This method will be called from standard filter destruction
273      * as well as filter bean destruction in a Spring application context.
274      * <p>This default implementation is empty.
275      */

276     public void destroy() {
277     }
278
279
280     /**
281      * PropertyValues implementation created from FilterConfig init parameters.
282      */

283     private static class FilterConfigPropertyValues extends MutablePropertyValues {
284
285         /**
286          * Create new FilterConfigPropertyValues.
287          * @param config FilterConfig we'll use to take PropertyValues from
288          * @param requiredProperties set of property names we need, where
289          * we can't accept default values
290          * @throws ServletException if any required properties are missing
291          */

292         public FilterConfigPropertyValues(FilterConfig JavaDoc config, Set JavaDoc requiredProperties)
293             throws ServletException JavaDoc {
294
295             Set JavaDoc missingProps = (requiredProperties != null && !requiredProperties.isEmpty()) ?
296                     new HashSet JavaDoc(requiredProperties) : null;
297
298             Enumeration JavaDoc en = config.getInitParameterNames();
299             while (en.hasMoreElements()) {
300                 String JavaDoc property = (String JavaDoc) en.nextElement();
301                 Object JavaDoc value = config.getInitParameter(property);
302                 addPropertyValue(new PropertyValue(property, value));
303                 if (missingProps != null) {
304                     missingProps.remove(property);
305                 }
306             }
307
308             // Fail if we are still missing properties.
309
if (missingProps != null && missingProps.size() > 0) {
310                 throw new ServletException JavaDoc(
311                     "Initialization from FilterConfig for filter '" + config.getFilterName() +
312                     "' failed; the following required properties were missing: " +
313                     StringUtils.collectionToDelimitedString(missingProps, ", "));
314             }
315         }
316     }
317
318 }
319
Popular Tags