Revisit synchonization issue and correct problem identified by Volker Malzahn.

This commit is contained in:
Ben Alex 2005-08-21 10:10:16 +00:00
parent e805aa2e73
commit 40a81ed220

View File

@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.sf.acegisecurity.util; package net.sf.acegisecurity.util;
import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.BeanFactoryUtils;
@ -35,13 +34,13 @@ import javax.servlet.ServletResponse;
/** /**
* Delegates <code>Filter</code> requests to a Spring-managed bean. * Delegates <code>Filter</code> requests to a Spring-managed bean.
* *
* <p> * <p>
* This class acts as a proxy on behalf of a target <code>Filter</code> that is * This class acts as a proxy on behalf of a target <code>Filter</code> that is
* defined in the Spring bean context. It is necessary to specify which target * defined in the Spring bean context. It is necessary to specify which target
* <code>Filter</code> should be proxied as a filter initialization parameter. * <code>Filter</code> should be proxied as a filter initialization parameter.
* </p> * </p>
* *
* <p> * <p>
* On filter initialisation, the class will use Spring's {@link * On filter initialisation, the class will use Spring's {@link
* WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)} * WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)}
@ -49,12 +48,12 @@ import javax.servlet.ServletResponse;
* expect to find the target <code>Filter</code> in this * expect to find the target <code>Filter</code> in this
* <code>ApplicationContext</code>. * <code>ApplicationContext</code>.
* </p> * </p>
* *
* <p> * <p>
* To use this filter, it is necessary to specify <b>one</b> of the following * To use this filter, it is necessary to specify <b>one</b> of the following
* filter initialization parameters: * filter initialization parameters:
* </p> * </p>
* *
* <ul> * <ul>
* <li> * <li>
* <code>targetClass</code> indicates the class of the target * <code>targetClass</code> indicates the class of the target
@ -67,10 +66,10 @@ import javax.servlet.ServletResponse;
* <code>targetBean</code> indicates the bean name of the target class. * <code>targetBean</code> indicates the bean name of the target class.
* </li> * </li>
* </ul> * </ul>
* *
* If both initialization parameters are specified, <code>targetBean</code> * If both initialization parameters are specified, <code>targetBean</code>
* takes priority. * takes priority.
* *
* <P> * <P>
* An additional initialization parameter, <code>init</code>, is also * An additional initialization parameter, <code>init</code>, is also
* supported. If set to "<code>lazy</code>" the initialization will take place * supported. If set to "<code>lazy</code>" the initialization will take place
@ -79,7 +78,7 @@ import javax.servlet.ServletResponse;
* <code>ContextLoaderServlet</code>. Where possible you should not use this * <code>ContextLoaderServlet</code>. Where possible you should not use this
* initialization parameter, instead using <code>ContextLoaderListener</code>. * initialization parameter, instead using <code>ContextLoaderListener</code>.
* </p> * </p>
* *
* <p> * <p>
* A final optional initialization parameter, <code>lifecycle</code>, * A final optional initialization parameter, <code>lifecycle</code>,
* determines whether the servlet container or the IoC container manages the * determines whether the servlet container or the IoC container manages the
@ -101,15 +100,11 @@ import javax.servlet.ServletResponse;
* @version $Id$ * @version $Id$
*/ */
public class FilterToBeanProxy implements Filter { public class FilterToBeanProxy implements Filter {
//~ Instance fields ========================================================
private Filter delegate; private Filter delegate;
private FilterConfig filterConfig; private FilterConfig filterConfig;
private boolean initialized = false; private boolean initialized = false;
private boolean servletContainerManaged = false; private boolean servletContainerManaged = false;
//~ Methods ================================================================
public void destroy() { public void destroy() {
if ((delegate != null) && servletContainerManaged) { if ((delegate != null) && servletContainerManaged) {
delegate.destroy(); delegate.destroy();
@ -146,8 +141,7 @@ public class FilterToBeanProxy implements Filter {
* @return the Spring application context * @return the Spring application context
*/ */
protected ApplicationContext getContext(FilterConfig filterConfig) { protected ApplicationContext getContext(FilterConfig filterConfig) {
return WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig return WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext());
.getServletContext());
} }
private synchronized void doInit() throws ServletException { private synchronized void doInit() throws ServletException {
@ -156,8 +150,6 @@ public class FilterToBeanProxy implements Filter {
return; return;
} }
initialized = true;
String targetBean = filterConfig.getInitParameter("targetBean"); String targetBean = filterConfig.getInitParameter("targetBean");
if ("".equals(targetBean)) { if ("".equals(targetBean)) {
@ -177,8 +169,8 @@ public class FilterToBeanProxy implements Filter {
if ((targetBean != null) && ctx.containsBean(targetBean)) { if ((targetBean != null) && ctx.containsBean(targetBean)) {
beanName = targetBean; beanName = targetBean;
} else if (targetBean != null) { } else if (targetBean != null) {
throw new ServletException("targetBean '" + targetBean throw new ServletException("targetBean '" + targetBean +
+ "' not found in context"); "' not found in context");
} else { } else {
String targetClassString = filterConfig.getInitParameter( String targetClassString = filterConfig.getInitParameter(
"targetClass"); "targetClass");
@ -194,8 +186,8 @@ public class FilterToBeanProxy implements Filter {
targetClass = Thread.currentThread().getContextClassLoader() targetClass = Thread.currentThread().getContextClassLoader()
.loadClass(targetClassString); .loadClass(targetClassString);
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
throw new ServletException("Class of type " + targetClassString throw new ServletException("Class of type " +
+ " not found in classloader"); targetClassString + " not found in classloader");
} }
Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx, Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx,
@ -203,8 +195,8 @@ public class FilterToBeanProxy implements Filter {
if (beans.size() == 0) { if (beans.size() == 0) {
throw new ServletException( throw new ServletException(
"Bean context must contain at least one bean of type " "Bean context must contain at least one bean of type " +
+ targetClassString); targetClassString);
} }
beanName = (String) beans.keySet().iterator().next(); beanName = (String) beans.keySet().iterator().next();
@ -213,8 +205,8 @@ public class FilterToBeanProxy implements Filter {
Object object = ctx.getBean(beanName); Object object = ctx.getBean(beanName);
if (!(object instanceof Filter)) { if (!(object instanceof Filter)) {
throw new ServletException("Bean '" + beanName throw new ServletException("Bean '" + beanName +
+ "' does not implement javax.servlet.Filter"); "' does not implement javax.servlet.Filter");
} }
delegate = (Filter) object; delegate = (Filter) object;
@ -222,5 +214,10 @@ public class FilterToBeanProxy implements Filter {
if (servletContainerManaged) { if (servletContainerManaged) {
delegate.init(filterConfig); delegate.init(filterConfig);
} }
// Set initialized to true at the end of the synchronized method, so
// that invocations of doFilter() before this method has completed will not
// cause NullPointerException
initialized = true;
} }
} }