1 package org.springframework.security.config;
2
3 import java.io.IOException;
4
5 import javax.servlet.Filter;
6 import javax.servlet.FilterChain;
7 import javax.servlet.FilterConfig;
8 import javax.servlet.ServletException;
9 import javax.servlet.ServletRequest;
10 import javax.servlet.ServletResponse;
11
12 import org.springframework.beans.factory.config.BeanDefinitionHolder;
13 import org.springframework.beans.factory.config.RuntimeBeanReference;
14 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
15 import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
16 import org.springframework.beans.factory.xml.ParserContext;
17 import org.springframework.core.Ordered;
18 import org.springframework.security.ui.FilterChainOrder;
19 import org.springframework.util.Assert;
20 import org.springframework.util.StringUtils;
21 import org.w3c.dom.Element;
22 import org.w3c.dom.Node;
23
24
25
26
27
28
29
30
31
32 public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecorator {
33
34 public static final String ATT_AFTER = "after";
35 public static final String ATT_BEFORE = "before";
36 public static final String ATT_POSITION = "position";
37
38 public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) {
39 Element elt = (Element)node;
40 String order = getOrder(elt, parserContext);
41
42 BeanDefinitionBuilder wrapper = BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.config.OrderedFilterBeanDefinitionDecorator$OrderedFilterDecorator");
43 wrapper.addConstructorArg(holder.getBeanName());
44 wrapper.addConstructorArg(new RuntimeBeanReference(holder.getBeanName()));
45
46 if (StringUtils.hasText(order)) {
47 wrapper.addPropertyValue("order", order);
48 }
49
50 ConfigUtils.addHttpFilter(parserContext, wrapper.getBeanDefinition());
51
52 return holder;
53 }
54
55
56
57
58 private String getOrder(Element elt, ParserContext pc) {
59 String after = elt.getAttribute(ATT_AFTER);
60 String before = elt.getAttribute(ATT_BEFORE);
61 String position = elt.getAttribute(ATT_POSITION);
62
63 if(ConfigUtils.countNonEmpty(new String[] {after, before, position}) != 1) {
64 pc.getReaderContext().error("A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" +
65 ATT_POSITION + "' attribute must be supplied", pc.extractSource(elt));
66 }
67
68 if (StringUtils.hasText(position)) {
69 return Integer.toString(FilterChainOrder.getOrder(position));
70 }
71
72 if (StringUtils.hasText(after)) {
73 int order = FilterChainOrder.getOrder(after);
74
75 return Integer.toString(order == Integer.MAX_VALUE ? order : order + 1);
76 }
77
78 if (StringUtils.hasText(before)) {
79 int order = FilterChainOrder.getOrder(before);
80
81 return Integer.toString(order == Integer.MIN_VALUE ? order : order - 1);
82 }
83
84 return null;
85 }
86
87 static class OrderedFilterDecorator implements Filter, Ordered {
88 private Integer order = null;
89 private Filter delegate;
90 private String beanName;
91
92 OrderedFilterDecorator(String beanName, Filter delegate) {
93 this.delegate = delegate;
94 this.beanName = beanName;
95 }
96
97 public final void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
98 delegate.doFilter(request, response, chain);
99 }
100
101 public final void init(FilterConfig filterConfig) throws ServletException {
102 delegate.init(filterConfig);
103 }
104
105 public final void destroy() {
106 delegate.destroy();
107 }
108
109 public final int getOrder() {
110 if(order == null) {
111 Assert.isInstanceOf(Ordered.class, delegate, "Filter '"+ beanName +"' must implement the 'Ordered' interface " +
112 " or you must specify one of the attributes '" + ATT_AFTER + "' or '" +
113 ATT_BEFORE + "' in <" + Elements.CUSTOM_FILTER +">");
114
115 return ((Ordered)delegate).getOrder();
116 }
117 return order.intValue();
118 }
119
120 public final void setOrder(int order) {
121 this.order = new Integer(order);
122 }
123
124 public String getBeanName() {
125 return beanName;
126 }
127
128 public String toString() {
129 return "OrderedFilterDecorator[ delegate=" + delegate + "; order=" + getOrder() + "]";
130 }
131
132 Filter getDelegate() {
133 return delegate;
134 }
135 }
136 }