KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > acting > HttpCacheAction


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
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 package org.apache.cocoon.acting;
17
18 import org.apache.avalon.framework.configuration.Configuration;
19 import org.apache.avalon.framework.configuration.ConfigurationException;
20 import org.apache.avalon.framework.parameters.Parameters;
21 import org.apache.avalon.framework.thread.ThreadSafe;
22 import org.apache.cocoon.environment.ObjectModelHelper;
23 import org.apache.cocoon.environment.Redirector;
24 import org.apache.cocoon.environment.Response;
25 import org.apache.cocoon.environment.SourceResolver;
26 import org.apache.commons.lang.time.DateUtils;
27 import org.apache.commons.lang.time.FastDateFormat;
28
29 import java.util.Calendar JavaDoc;
30 import java.util.Collections JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Map JavaDoc;
33
34 /**
35  * This action adds the <code>Last-Modified</code>, <code>Expires</code> and
36  * <code>Cache-Control</code> HTTP headers to the response.
37  *
38  * <p>
39  * This action will add the <code>Last-Modified</code> header to the response
40  * with the time in which the request was executed, and an <code>Expires</code>
41  * header at a specified time difference. Additionally, it will provide an
42  * extra <code>Cache-Control</code> indicating the maximum age of the request
43  * as a delta between the expiration and last modification dates.
44  * </p>
45  * <p>
46  * This is useful (for example) when Cocoon is proxyied by a Web Server such
47  * as Apache HTTPD running mod_cache, to indicate for each request how long
48  * the output should be cached for.
49  * </p>
50  * <p>
51  * To configure the difference between <code>Last-Modified</code> and
52  * <code>Expires</code> this <code>Action</code> can be configured specifying
53  * days, hours, minutes, and seconds in this way:
54  * </p>
55  * <pre>
56  * &lt;map:action&gt;s
57  * &lt;map:action name="xyz" SRC="org.apache.cocoon.acting.HttpCacheAction&gt;"
58  * &lt;days&gt;1&lt;/day&gt;s
59  * &lt;hours&gt;2&lt;/hour&gt;s
60  * &lt;minutes&gt;3&lt;/minute&gt;s
61  * &lt;seconds&gt;4&lt;/second&gt;s
62  * &lt;/map:actio&gt;n
63  * &lt;/map:action&gt;s
64  * </pre>
65  * <p>
66  * Using this example configuration, the <code>Expires</code> header will
67  * specify a date one day, two hours, three minutes and four seconds after
68  * the time of the request (which will be in <code>Last-Modified</code>).
69  * </p>
70  * <p>
71  * Note that if any of the parameters mentioned above is <b>zero</b> or
72  * <b>less than zero</b> this action will modify the behaviour of the
73  * resulting <code>Cache-Control</code> header to emit the keyword
74  * <code>no-cache</code>.
75  * </p>
76  * <p>
77  * This action will also return the three headers it added as sitemap
78  * parameters called <code>last-modified</code>, <code>expires</code> and
79  * <code>cache-control</code> (all lowercase).
80  * </p>
81  *
82  * @author <a HREF="mailto:pier@apache.org">Pier Fumagalli</a>
83  * @version CVS $Id: HttpCacheAction.java 30941 2004-07-29 19:56:58Z vgritsenko $
84  */

85 public class HttpCacheAction extends AbstractConfigurableAction implements ThreadSafe {
86
87     private FastDateFormat formatter = null;
88     int days = 0;
89     int hours = 0;
90     int minutes = 0;
91     int seconds = 0;
92
93     public void configure(Configuration configuration)
94     throws ConfigurationException {
95         super.configure(configuration);
96
97         // RFC-822 Date with a GMT based time zone
98
this.formatter = FastDateFormat.getInstance("EEE, dd MMM yyyy kk:mm:ss zzz", DateUtils.UTC_TIME_ZONE);
99         this.days = configuration.getChild("days").getValueAsInteger(0);
100         this.hours = configuration.getChild("hours").getValueAsInteger(0);
101         this.minutes = configuration.getChild("minutes").getValueAsInteger(0);
102         this.seconds = configuration.getChild("seconds").getValueAsInteger(0);
103     }
104
105     public Map JavaDoc act(Redirector redirector, SourceResolver resolver,
106                    Map JavaDoc objectModel, String JavaDoc source, Parameters parameters)
107     throws Exception JavaDoc {
108         Response response = ObjectModelHelper.getResponse(objectModel);
109         Calendar JavaDoc calendar = Calendar.getInstance(DateUtils.UTC_TIME_ZONE);
110         Map JavaDoc values = new HashMap JavaDoc(3);
111
112         /* Get the current time and output as the last modified header */
113         String JavaDoc value = this.formatter.format(calendar);
114         long maxage = calendar.getTime().getTime();
115         response.setHeader("Last-Modified", value);
116         values.put("last-modified", value);
117
118         /* Advance the time as much as required */
119         calendar.add(Calendar.DATE, this.days);
120         calendar.add(Calendar.HOUR, this.hours);
121         calendar.add(Calendar.MINUTE, this.minutes);
122         calendar.add(Calendar.SECOND, this.seconds);
123
124         /* Recalculate time and age to see what changed */
125         maxage = calendar.getTime().getTime() - maxage;
126
127         /* If we got more than one second everything is quite normal */
128         if (maxage > 1000) {
129             value = this.formatter.format(calendar);
130             response.setHeader("Expires", value);
131             values.put("expires", value);
132
133             value = "max-age=" + Long.toString(maxage / 1000l);
134             response.setHeader("Cache-Control", value);
135             values.put("cache-control", value);
136
137         /* If we got less than one second (even negatives) no cache */
138         } else {
139             /* We still hold the old value from Last-Modified here */
140             response.setHeader("Expires", value);
141             values.put("expires", value);
142
143             response.setHeader("Cache-Control", "no-cache");
144             values.put("cache-control", "no-cache");
145         }
146
147         /* Return the headers */
148         return(Collections.unmodifiableMap(values));
149     }
150 }
151
Popular Tags