|
27 | 27 | import javax.servlet.ServletRequest; |
28 | 28 | import javax.servlet.ServletResponse; |
29 | 29 | import javax.servlet.http.HttpServletResponse; |
| 30 | +import javax.servlet.http.HttpServletResponseWrapper; |
30 | 31 |
|
31 | 32 | import com.samaxes.filter.util.CacheConfigParameter; |
32 | 33 | import com.samaxes.filter.util.Cacheability; |
|
137 | 138 | * |
138 | 139 | * @author Samuel Santos |
139 | 140 | * @author John Yeary |
140 | | - * @version 2.1.0 |
| 141 | + * @version 2.2.0 |
141 | 142 | */ |
142 | 143 | public class CacheFilter implements Filter { |
143 | 144 |
|
144 | | - private Cacheability cacheability; |
| 145 | + private long expiration; |
145 | 146 |
|
146 | | - private boolean isStatic; |
| 147 | + private Cacheability cacheability; |
147 | 148 |
|
148 | | - private long seconds; |
| 149 | + private boolean mustRevalidate; |
149 | 150 |
|
150 | 151 | /** |
151 | 152 | * {@inheritDoc} |
152 | 153 | */ |
153 | 154 | @Override |
154 | 155 | public void init(FilterConfig filterConfig) throws ServletException { |
155 | | - cacheability = (Boolean.valueOf(filterConfig.getInitParameter(CacheConfigParameter.PRIVATE.getName()))) ? Cacheability.PRIVATE |
156 | | - : Cacheability.PUBLIC; |
157 | | - isStatic = Boolean.valueOf(filterConfig.getInitParameter(CacheConfigParameter.STATIC.getName())); |
| 156 | + if (filterConfig.getInitParameter("expirationTime") != null) { |
| 157 | + throw new ServletException(new StringBuilder( |
| 158 | + "The initialization parameter expirationTime has been replaced with ") |
| 159 | + .append(CacheConfigParameter.EXPIRATION.getName()).append(" for the filter ") |
| 160 | + .append(filterConfig.getFilterName()).append(".").toString()); |
| 161 | + } |
| 162 | + if (filterConfig.getInitParameter("static") != null) { |
| 163 | + throw new ServletException(new StringBuilder("The initialization parameter static has been replaced with ") |
| 164 | + .append(CacheConfigParameter.MUST_REVALIDATE.getName()).append(" for the filter ") |
| 165 | + .append(filterConfig.getFilterName()).append(".").toString()); |
| 166 | + } |
158 | 167 |
|
159 | 168 | try { |
160 | | - seconds = Long.valueOf(filterConfig.getInitParameter(CacheConfigParameter.EXPIRATION_TIME.getName())); |
| 169 | + expiration = Long.valueOf(filterConfig.getInitParameter(CacheConfigParameter.EXPIRATION.getName())); |
161 | 170 | } catch (NumberFormatException e) { |
162 | 171 | throw new ServletException(new StringBuilder("The initialization parameter ") |
163 | | - .append(CacheConfigParameter.EXPIRATION_TIME.getName()).append(" is missing for filter ") |
164 | | - .append(filterConfig.getFilterName()).append(".").toString()); |
| 172 | + .append(CacheConfigParameter.EXPIRATION.getName()) |
| 173 | + .append(" is invalid or is missing for the filter ").append(filterConfig.getFilterName()) |
| 174 | + .append(".").toString()); |
165 | 175 | } |
| 176 | + cacheability = Boolean.valueOf(filterConfig.getInitParameter(CacheConfigParameter.PRIVATE.getName())) ? Cacheability.PRIVATE |
| 177 | + : Cacheability.PUBLIC; |
| 178 | + mustRevalidate = Boolean.valueOf(filterConfig.getInitParameter(CacheConfigParameter.MUST_REVALIDATE.getName())); |
166 | 179 | } |
167 | 180 |
|
168 | 181 | /** |
169 | | - * Set cache header directives. {@inheritDoc} |
| 182 | + * <p> |
| 183 | + * Set HTTP cache headers. |
| 184 | + * </p> |
| 185 | + * {@inheritDoc} |
170 | 186 | */ |
171 | 187 | @Override |
172 | 188 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) |
173 | 189 | throws IOException, ServletException { |
174 | 190 | HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse; |
175 | | - StringBuilder cacheControl = new StringBuilder(cacheability.getValue()).append(", max-age=").append(seconds); |
176 | | - |
177 | | - if (!isStatic) { |
| 191 | + StringBuilder cacheControl = new StringBuilder(cacheability.getValue()).append(", max-age=").append(expiration); |
| 192 | + if (mustRevalidate) { |
178 | 193 | cacheControl.append(", must-revalidate"); |
179 | 194 | } |
180 | 195 |
|
181 | 196 | // Set cache directives |
182 | 197 | httpServletResponse.setHeader(HTTPCacheHeader.CACHE_CONTROL.getName(), cacheControl.toString()); |
183 | | - httpServletResponse.setDateHeader(HTTPCacheHeader.EXPIRES.getName(), System.currentTimeMillis() + seconds |
| 198 | + httpServletResponse.setDateHeader(HTTPCacheHeader.EXPIRES.getName(), System.currentTimeMillis() + expiration |
184 | 199 | * 1000L); |
185 | 200 |
|
186 | 201 | /* |
187 | | - * By default, some servers (e.g. Tomcat) will set headers on any SSL content to deny caching. Setting the |
188 | | - * Pragma header to null or to an empty string takes care of user-agents implementing HTTP 1.0. |
| 202 | + * By default, some servers (e.g. Tomcat) will set headers on any SSL content to deny caching. Omitting the |
| 203 | + * Pragma header takes care of user-agents implementing HTTP/1.0. |
189 | 204 | */ |
190 | | - if (httpServletResponse.containsHeader("Pragma")) { |
191 | | - httpServletResponse.setHeader(HTTPCacheHeader.PRAGMA.getName(), null); |
192 | | - } |
| 205 | + filterChain.doFilter(servletRequest, new HttpServletResponseWrapper(httpServletResponse) { |
| 206 | + @Override |
| 207 | + public void addHeader(String name, String value) { |
| 208 | + if (!HTTPCacheHeader.PRAGMA.getName().equalsIgnoreCase(name)) { |
| 209 | + super.addHeader(name, value); |
| 210 | + } |
| 211 | + } |
193 | 212 |
|
194 | | - filterChain.doFilter(servletRequest, servletResponse); |
| 213 | + @Override |
| 214 | + public void setHeader(String name, String value) { |
| 215 | + if (!HTTPCacheHeader.PRAGMA.getName().equalsIgnoreCase(name)) { |
| 216 | + super.setHeader(name, value); |
| 217 | + } |
| 218 | + } |
| 219 | + }); |
195 | 220 | } |
196 | 221 |
|
197 | 222 | /** |
|
0 commit comments