KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > web > servlet > support > WebContentGenerator


1 /*
2  * Copyright 2002-2006 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.servlet.support;
18
19 import java.util.HashSet JavaDoc;
20 import java.util.Set JavaDoc;
21
22 import javax.servlet.ServletException JavaDoc;
23 import javax.servlet.http.HttpServletRequest JavaDoc;
24 import javax.servlet.http.HttpServletResponse JavaDoc;
25
26 import org.springframework.util.StringUtils;
27 import org.springframework.web.HttpRequestMethodNotSupportedException;
28 import org.springframework.web.HttpSessionRequiredException;
29 import org.springframework.web.context.support.WebApplicationObjectSupport;
30
31 /**
32  * Convenient superclass for any kind of web content generator,
33  * like AbstractController and WebContentInterceptor. Can also
34  * be used for custom handlers that have their own
35  * {@link org.springframework.web.servlet.HandlerAdapter}.
36  *
37  * <p>Supports HTTP cache control options. The usage of corresponding
38  * HTTP headers can be determined via the "useExpiresHeader" and
39  * "userCacheControlHeader" properties.
40  *
41  * @author Rod Johnson
42  * @author Juergen Hoeller
43  * @see #setUseExpiresHeader
44  * @see #setUseCacheControlHeader
45  * @see org.springframework.web.servlet.mvc.AbstractController
46  * @see org.springframework.web.servlet.mvc.WebContentInterceptor
47  */

48 public abstract class WebContentGenerator extends WebApplicationObjectSupport {
49
50     /** HTTP method "HEAD" */
51     public static final String JavaDoc METHOD_HEAD = "HEAD";
52
53     /** HTTP method "GET" */
54     public static final String JavaDoc METHOD_GET = "GET";
55
56     /** HTTP method "POST" */
57     public static final String JavaDoc METHOD_POST = "POST";
58
59
60     private static final String JavaDoc HEADER_PRAGMA = "Pragma";
61
62     private static final String JavaDoc HEADER_EXPIRES = "Expires";
63
64     private static final String JavaDoc HEADER_CACHE_CONTROL = "Cache-Control";
65
66
67     /** Set of supported methods. HEAD, GET and POST by default. */
68     private Set JavaDoc supportedMethods = new HashSet JavaDoc();
69
70     private boolean requireSession = false;
71
72     /** Use HTTP 1.0 expires header? */
73     private boolean useExpiresHeader = true;
74
75     /** Use HTTP 1.1 cache-control header? */
76     private boolean useCacheControlHeader = true;
77
78     private int cacheSeconds = -1;
79
80
81     public WebContentGenerator() {
82         this.supportedMethods.add(METHOD_HEAD);
83         this.supportedMethods.add(METHOD_GET);
84         this.supportedMethods.add(METHOD_POST);
85     }
86
87     /**
88      * Set the HTTP methods that this content generator should support.
89      * Default is HEAD, GET and POST.
90      */

91     public final void setSupportedMethods(String JavaDoc[] methods) {
92         if (methods == null || methods.length == 0) {
93             throw new IllegalArgumentException JavaDoc("supportedMethods must not be empty");
94         }
95         this.supportedMethods.clear();
96         for (int i = 0; i < methods.length; i++) {
97             this.supportedMethods.add(methods[i]);
98         }
99     }
100
101     /**
102      * Return the HTTP methods that this content generator supports.
103      */

104     public final String JavaDoc[] getSupportedMethods() {
105         return StringUtils.toStringArray(this.supportedMethods);
106     }
107
108     /**
109      * Set whether a session should be required to handle requests.
110      */

111     public final void setRequireSession(boolean requireSession) {
112         this.requireSession = requireSession;
113     }
114
115     /**
116      * Return whether a session is required to handle requests.
117      */

118     public final boolean isRequireSession() {
119         return requireSession;
120     }
121
122     /**
123      * Set whether to use the HTTP 1.0 expires header. Default is "true".
124      * <p>Note: Cache headers will only get applied if caching is enabled
125      * for the current request.
126      */

127     public final void setUseExpiresHeader(boolean useExpiresHeader) {
128         this.useExpiresHeader = useExpiresHeader;
129     }
130
131     /**
132      * Return whether the HTTP 1.0 expires header is used.
133      */

134     public final boolean isUseExpiresHeader() {
135         return useExpiresHeader;
136     }
137
138     /**
139      * Set whether to use the HTTP 1.1 cache-control header. Default is "true".
140      * <p>Note: Cache headers will only get applied if caching is enabled
141      * for the current request.
142      */

143     public final void setUseCacheControlHeader(boolean useCacheControlHeader) {
144         this.useCacheControlHeader = useCacheControlHeader;
145     }
146
147     /**
148      * Return whether the HTTP 1.1 cache-control header is used.
149      */

150     public final boolean isUseCacheControlHeader() {
151         return useCacheControlHeader;
152     }
153
154     /**
155      * Cache content for the given number of seconds. Default is -1,
156      * indicating no generation of cache-related headers.
157      * <p>Only if this is set to 0 (no cache) or a positive value (cache for
158      * this many seconds) will this class generate cache headers.
159      * <p>The headers can be overwritten by subclasses, before content is generated.
160      */

161     public final void setCacheSeconds(int seconds) {
162         this.cacheSeconds = seconds;
163     }
164
165     /**
166      * Return the number of seconds that content is cached.
167      */

168     public final int getCacheSeconds() {
169         return cacheSeconds;
170     }
171
172
173     /**
174      * Check and prepare the given request and response according to the settings
175      * of this generator. Checks for supported methods and a required session,
176      * and applies the number of cache seconds specified for this generator.
177      * @param request current HTTP request
178      * @param response current HTTP response
179      * @param lastModified if the mapped handler provides Last-Modified support
180      * @throws ServletException if the request cannot be handled because a check failed
181      */

182     protected final void checkAndPrepare(
183             HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, boolean lastModified)
184         throws ServletException JavaDoc {
185
186         checkAndPrepare(request, response, this.cacheSeconds, lastModified);
187     }
188
189     /**
190      * Check and prepare the given request and response according to the settings
191      * of this generator. Checks for supported methods and a required session,
192      * and applies the given number of cache seconds.
193      * @param request current HTTP request
194      * @param response current HTTP response
195      * @param cacheSeconds positive number of seconds into the future that the
196      * response should be cacheable for, 0 to prevent caching
197      * @param lastModified if the mapped handler provides Last-Modified support
198      * @throws ServletException if the request cannot be handled because a check failed
199      */

200     protected final void checkAndPrepare(
201             HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, int cacheSeconds, boolean lastModified)
202         throws ServletException JavaDoc {
203
204         // Check whether we should support the request method.
205
String JavaDoc method = request.getMethod();
206         if (!this.supportedMethods.contains(method)) {
207             throw new HttpRequestMethodNotSupportedException(method);
208         }
209
210         // Check whether a session is required.
211
if (this.requireSession) {
212             if (request.getSession(false) == null) {
213                 throw new HttpSessionRequiredException("Pre-existing session required but none found");
214             }
215         }
216
217         // Do declarative cache control.
218
// Revalidate if the controller supports last-modified.
219
applyCacheSeconds(response, cacheSeconds, lastModified);
220     }
221
222     /**
223      * Prevent the response from being cached.
224      * See www.mnot.net.cache docs.
225      */

226     protected final void preventCaching(HttpServletResponse JavaDoc response) {
227         response.setHeader(HEADER_PRAGMA, "No-cache");
228         if (this.useExpiresHeader) {
229             // HTTP 1.0 header
230
response.setDateHeader(HEADER_EXPIRES, 1L);
231         }
232         if (this.useCacheControlHeader) {
233             // HTTP 1.1 header: "no-cache" is the standard value,
234
// "no-store" is necessary to prevent caching on FireFox.
235
response.setHeader(HEADER_CACHE_CONTROL, "no-cache");
236             response.addHeader(HEADER_CACHE_CONTROL, "no-store");
237         }
238     }
239
240     /**
241      * Set HTTP headers to allow caching for the given number of seconds.
242      * Does not tell the browser to revalidate the resource.
243      * @param response current HTTP response
244      * @param seconds number of seconds into the future that the response
245      * should be cacheable for
246      * @see #cacheForSeconds(javax.servlet.http.HttpServletResponse, int, boolean)
247      */

248     protected final void cacheForSeconds(HttpServletResponse JavaDoc response, int seconds) {
249         cacheForSeconds(response, seconds, false);
250     }
251
252     /**
253      * Set HTTP headers to allow caching for the given number of seconds.
254      * Tells the browser to revalidate the resource if mustRevalidate is
255      * <code>true</code>.
256      * @param response the current HTTP response
257      * @param seconds number of seconds into the future that the response
258      * should be cacheable for
259      * @param mustRevalidate whether the client should revalidate the resource
260      * (typically only necessary for controllers with last-modified support)
261      */

262     protected final void cacheForSeconds(HttpServletResponse JavaDoc response, int seconds, boolean mustRevalidate) {
263         if (this.useExpiresHeader) {
264             // HTTP 1.0 header
265
response.setDateHeader(HEADER_EXPIRES, System.currentTimeMillis() + seconds * 1000L);
266         }
267         if (this.useCacheControlHeader) {
268             // HTTP 1.1 header
269
String JavaDoc headerValue = "max-age=" + seconds;
270             if (mustRevalidate) {
271                 headerValue += ", must-revalidate";
272             }
273             response.setHeader(HEADER_CACHE_CONTROL, headerValue);
274         }
275     }
276
277     /**
278      * Apply the given cache seconds and generate corresponding HTTP headers,
279      * i.e. allow caching for the given number of seconds in case of a positive
280      * value, prevent caching if given a 0 value, do nothing else.
281      * Does not tell the browser to revalidate the resource.
282      * @param response current HTTP response
283      * @param seconds positive number of seconds into the future that the
284      * response should be cacheable for, 0 to prevent caching
285      * @see #cacheForSeconds(javax.servlet.http.HttpServletResponse, int, boolean)
286      */

287     protected final void applyCacheSeconds(HttpServletResponse JavaDoc response, int seconds) {
288         applyCacheSeconds(response, seconds, false);
289     }
290
291     /**
292      * Apply the given cache seconds and generate respective HTTP headers.
293      * <p>That is, allow caching for the given number of seconds in the
294      * case of a positive value, prevent caching if given a 0 value, else
295      * do nothing (i.e. leave caching to the client).
296      * @param response the current HTTP response
297      * @param seconds the (positive) number of seconds into the future that
298      * the response should be cacheable for; 0 to prevent caching; and
299      * a negative value to leave caching to the client.
300      * @param mustRevalidate whether the client should revalidate the resource
301      * (typically only necessary for controllers with last-modified support)
302      */

303     protected final void applyCacheSeconds(HttpServletResponse JavaDoc response, int seconds, boolean mustRevalidate) {
304         if (seconds > 0) {
305             cacheForSeconds(response, seconds, mustRevalidate);
306         }
307         else if (seconds == 0) {
308             preventCaching(response);
309         }
310         // Leave caching to the client otherwise.
311
}
312
313 }
314
Popular Tags