cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject cvs commit: cocoon-2.1/src/java/org/apache/cocoon/acting
Date Wed, 30 Jun 2004 16:38:41 GMT
pier        2004/06/30 09:38:41

  Added:       src/java/org/apache/cocoon/acting
  Added simple action generating HTTP caching headers to be used in conjunction with mod_proxy
  Revision  Changes    Path
  1.1                  cocoon-2.1/src/java/org/apache/cocoon/acting/
   * Copyright 1999-2004 The Apache Software Foundation.
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
  package org.apache.cocoon.acting;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.thread.ThreadSafe;
  import org.apache.cocoon.environment.ObjectModelHelper;
  import org.apache.cocoon.environment.Redirector;
  import org.apache.cocoon.environment.Response;
  import org.apache.cocoon.environment.SourceResolver;
  import java.text.SimpleDateFormat;
  import java.util.Calendar;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.TimeZone;
   * This action adds the <code>Last-Modified</code>, <code>Expires</code>
   * <code>Cache-Control</code> HTTP headers to the response.
   * <p>
   * This action will add the <code>Last-Modified</code> header to the response
   * with the time in which the request was executed, and an <code>Expires</code>
   * header at a specified time difference. Additionally, it will provide an
   * extra <code>Cache-Control</code> indicating the maximum age of the request
   * as a delta between the expiration and last modification dates.
   * </p>
   * <p>
   * This is useful (for example) when Cocoon is proxyied by a Web Server such
   * as Apache HTTPD running mod_cache, to indicate for each request how long
   * the output should be cached for.
   * </p>
   * <p>
   * To configure the difference between <code>Last-Modified</code> and
   * <code>Expires</code> this <code>Action</code> can be configured
   * days, hours, minutes, and seconds in this way:
   * </p>
   * <pre>
   * &lt;map:action&gt;s
   *   &lt;map:action name="xyz" src="org.apache.cocoon.acting.HttpCacheAction&gt;"
   *     &lt;days&gt;1&lt;/day&gt;s
   *     &lt;hours&gt;2&lt;/hour&gt;s
   *     &lt;minutes&gt;3&lt;/minute&gt;s
   *     &lt;seconds&gt;4&lt;/second&gt;s
   *   &lt;/map:actio&gt;n
   * &lt;/map:action&gt;s
   * </pre>
   * <p>
   * Using this example configuration, the <code>Expires</code> header will
   * specify a date one day, two hours, three minutes and four seconds after
   * the time of the request (which will be in <code>Last-Modified</code>).
   * </p>
   * <p>
   * Note that if any of the parameters mentioned above is <b>zero</b> or
   * <b>less than zero</b> this action will modify the behaviour of the
   * resulting <code>Cache-Control</code> header to emit the keyword
   * <code>no-cache</code>.
   * </p>
   * <p>
   * This action will also return the three headers it added as sitemap
   * parameters called <code>last-modified</code>, <code>expires</code>
   * <code>cache-control</code> (all lowercase).
   * </p>
   * @author <a href="">Pier Fumagalli</a>
   * @version CVS $Id:,v 1.1 2004/06/30 16:38:41 pier Exp $
  public class HttpCacheAction extends AbstractConfigurableAction implements ThreadSafe {
      private TimeZone timezone = null;
      private SimpleDateFormat formatter = null;
      int days = 0;
      int hours = 0;
      int minutes = 0;
      int seconds = 0;
      public void configure(Configuration configuration)
      throws ConfigurationException {
          /* RFC-822 Date with a GMT based time zone */
          this.timezone = TimeZone.getTimeZone("GMT");
          this.formatter = new SimpleDateFormat("EEE, dd MMM yyyy kk:mm:ss zzz");
          this.days = configuration.getChild("days").getValueAsInteger(0);
          this.hours = configuration.getChild("hours").getValueAsInteger(0);
          this.minutes = configuration.getChild("minutes").getValueAsInteger(0);
          this.seconds = configuration.getChild("seconds").getValueAsInteger(0);
      public Map act(Redirector redirector, SourceResolver resolver,
                     Map objectModel, String source, Parameters parameters)
      throws Exception {
          Response response = ObjectModelHelper.getResponse(objectModel);
          Calendar calendar = Calendar.getInstance(timezone);
          Map values = new HashMap(3);
          /* Get the current time and output as the last modified header */
          String value = this.formatter.format(calendar.getTime());
          long maxage = calendar.getTimeInMillis();
          response.setHeader("Last-Modified", value);
          values.put("last-modified",  value);
          /* Advance the time as much as required */
          calendar.add(Calendar.DATE, this.days);
          calendar.add(Calendar.HOUR, this.hours);
          calendar.add(Calendar.MINUTE, this.minutes);
          calendar.add(Calendar.SECOND, this.seconds);
          /* Recalculate time and age to see what changed */
          maxage = calendar.getTimeInMillis() - maxage;
          /* If we got more than one second everything is quite normal */
          if (maxage > 1000) {
              value = this.formatter.format(calendar.getTime());
              response.setHeader("Expires", value);
              values.put("expires", value);
              value = "max-age=" + Long.toString(maxage / 1000l);
              response.setHeader("Cache-Control", value);
              values.put("cache-control", value);
          /* If we got less than one second (even negatives) no cache */
          } else {
              /* We still hold the old value from Last-Modified here */
              response.setHeader("Expires", value);
              values.put("expires", value);
              response.setHeader("Cache-Control", "no-cache");
              values.put("cache-control", "no-cache");
          /* Return the headers */

View raw message