greenrd     00/11/19 17:44:01

  Modified:    .        changes.xml
               src/org/apache/cocoon/cache Cache.java CocoonCache.java
                        NoCache.java
               src/org/apache/cocoon Engine.java
               src/org/apache/cocoon/formatter AbstractFormatter.java
               src/org/apache/cocoon/framework Page.java
               src/org/apache/cocoon/processor/xinclude
                        XIncludeProcessor.java
               src/org/apache/cocoon/processor/xslt XSLTProcessor.java
               src/org/apache/cocoon/processor/xsp xsp-java.xsl
                        XSPPage.java XSPProcessor.java
               src/org/apache/cocoon/producer ProducerFromFile.java
               xdocs    docs-book.xml site-book.xml
  Added:       src/org/apache/cocoon/framework Cacheable.java
               xdocs    caching.xml
  Log:
  caching updates and fixes
  
  Revision  Changes    Path
  1.150     +8 -1      xml-cocoon/changes.xml
  
  Index: changes.xml
  ===================================================================
  RCS file: /home/cvs/xml-cocoon/changes.xml,v
  retrieving revision 1.149
  retrieving revision 1.150
  diff -u -r1.149 -r1.150
  --- changes.xml       2000/11/19 20:38:51     1.149
  +++ changes.xml       2000/11/20 01:43:51     1.150
  @@ -4,7 +4,7 @@
   
   <!--
     History of Cocoon changes   
  -  $Id: changes.xml,v 1.149 2000/11/19 20:38:51 greenrd Exp $ 
  +  $Id: changes.xml,v 1.150 2000/11/20 01:43:51 greenrd Exp $ 
   -->
   
   <changes title="History of Changes">
  @@ -18,6 +18,13 @@
     </devs>
   
    <release version="@version@" date="@date@">
  +  <action dev="RDG" type="update">
  +   New caching interface introduced - org.apache.cocoon.framework.Cacheable
  +   and corresponding xsp tag xsp:cacheable. Incomplete cacheing documentation
  +   page added. Requests that there is no point
  +   in cacheing, will now not be cached. This was partly in response to
  +   LastModified oddities, and partly to improve memory usage efficiency.
  +  </action>
     <action dev="RDG" type="fix">
      Made store cleanup algorithm more aggressive. Hopefully this should clear
      up some of the OutOfMemoryErrors people have been having.
  @@ -139,7 +146,7 @@
      Added put-value to session taglib for JServ compatibility.
     </action>
     <action dev="RDG" type="fix" due-to="Hao Wang" due-to-email="[EMAIL 
PROTECTED]">
  -   Spaces are not trimmed from class names read from cocoon.properties (by 
Engine or Router)
  +   Spaces are now trimmed from class names read from cocoon.properties (by 
Engine or Router)
      so that extra spaces won't create odd startup errors.
     </action>
     <action dev="DB" type="fix" due-to="Peter Verhage" due-to-email="[EMAIL 
PROTECTED]">
  
  
  
  1.7       +2 -3      xml-cocoon/src/org/apache/cocoon/cache/Cache.java
  
  Index: Cache.java
  ===================================================================
  RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/cache/Cache.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- Cache.java        2000/11/01 20:12:40     1.6
  +++ Cache.java        2000/11/20 01:43:52     1.7
  @@ -1,4 +1,4 @@
  -/*-- $Id: Cache.java,v 1.6 2000/11/01 20:12:40 greenrd Exp $ --
  +/*-- $Id: Cache.java,v 1.7 2000/11/20 01:43:52 greenrd Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -57,7 +57,7 @@
    * The interface that all caching implementations must adhere to.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a>
  - * @version $Revision: 1.6 $Date: 2000/11/01 20:12:40 $
  + * @version $Revision: 1.7 $Date: 2000/11/20 01:43:52 $
    */
   
   public interface Cache extends Actor {
  @@ -76,8 +76,7 @@
   
       /**
        * Get the time that this request was added to the cache.
  -     * If the request is no longer in the cache (maybe it was
  -     * cleared due to low memory), just returns the current time.
  +     * If the request is not in the cache, just returns -1.
        */
       public long getLastModified(HttpServletRequest request);
   
  @@ -87,4 +86,4 @@
        */
       public void flush();
   
  -}
  \ No newline at end of file
  +}
  
  
  
  1.9       +6 -17     xml-cocoon/src/org/apache/cocoon/cache/CocoonCache.java
  
  Index: CocoonCache.java
  ===================================================================
  RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/cache/CocoonCache.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- CocoonCache.java  2000/11/14 22:02:57     1.8
  +++ CocoonCache.java  2000/11/20 01:43:52     1.9
  @@ -1,4 +1,4 @@
  -/*-- $Id: CocoonCache.java,v 1.8 2000/11/14 22:02:57 greenrd Exp $ --
  +/*-- $Id: CocoonCache.java,v 1.9 2000/11/20 01:43:52 greenrd Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -62,7 +62,7 @@
    * statically and dynamically generated.
    *
    * @author <a href="[EMAIL PROTECTED]">Stefano Mazzocchi</a>
  - * @version $Revision: 1.8 $Date: 2000/11/14 22:02:57 $
  + * @version $Revision: 1.9 $Date: 2000/11/20 01:43:52 $
    */
   public class CocoonCache implements Cache, Status {
   
  @@ -86,41 +86,30 @@
               return null;
           }
   
  -        boolean changed = false;
  -        Enumeration e = page.getChangeables();
  -        while (e.hasMoreElements()) {
  -            Changeable c = (Changeable) e.nextElement();
  -            changed = c.hasChanged(request);
  -            if (changed) {
  -                break;
  -            }
  -        }
  -
  +        boolean changed = page.hasChanged (request);
           if (changed) store.remove (encoded);
  -
           return (changed) ? null : page;
       }
   
       /**
        * Get the time that this request was added to the cache.
  -     * If the request is no longer in the cache (maybe it was
  -     * cleared due to low memory), just returns the current time.
  +     * If the request is not in the cache, returns -1.
        */
       public long getLastModified(HttpServletRequest request) {
         try {
  -        return store.getTime (request);
  +        return store.getTime (Utils.encode (request));
         }
         catch (NullPointerException ex) {
  -        return System.currentTimeMillis ();
  +        return -1;
         }
       }
   
       /**
  -     * This method inserts the page in cache and associates it
  +     * If the page is cacheable, inserts it in cache and associates it
        * with the given request.
        */
       public void setPage(Page page, HttpServletRequest request) {
  -        if (!page.isCached()) {
  +        if (!page.isCached() && page.isCacheable (request)) {
               page.setCached(true);
               this.store.hold(Utils.encode(request), page);
           }
  
  
  
  1.7       +3 -3      xml-cocoon/src/org/apache/cocoon/cache/NoCache.java
  
  Index: NoCache.java
  ===================================================================
  RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/cache/NoCache.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- NoCache.java      2000/11/01 20:12:38     1.6
  +++ NoCache.java      2000/11/20 01:43:52     1.7
  @@ -1,4 +1,4 @@
  -/*-- $Id: NoCache.java,v 1.6 2000/11/01 20:12:38 greenrd Exp $ --
  +/*-- $Id: NoCache.java,v 1.7 2000/11/20 01:43:52 greenrd Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -57,7 +57,7 @@
    * A caching implementation that doesn't cache anything :).
    *
    * @author <a href="[EMAIL PROTECTED]">Stefano Mazzocchi</a>
  - * @version $Revision: 1.6 $Date: 2000/11/01 20:12:38 $
  + * @version $Revision: 1.7 $Date: 2000/11/20 01:43:52 $
    */
   public class NoCache extends AbstractActor implements Cache, Status {
   
  @@ -74,13 +74,13 @@
       }
   
       /**
  -     * Just returns the current time.
  +     * Just returns -1.
        */
       public long getLastModified(HttpServletRequest request) {
  -      return System.currentTimeMillis ();
  +      return -1;
       }
   
       public String getStatus() {
           return "<b>No cache</b>";
       }
  -}
  \ No newline at end of file
  +}
  
  
  
  1.38      +10 -4     xml-cocoon/src/org/apache/cocoon/Engine.java
  
  Index: Engine.java
  ===================================================================
  RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/Engine.java,v
  retrieving revision 1.37
  retrieving revision 1.38
  diff -u -r1.37 -r1.38
  --- Engine.java       2000/11/16 17:31:53     1.37
  +++ Engine.java       2000/11/20 01:43:53     1.38
  @@ -1,4 +1,4 @@
  -/*-- $Id: Engine.java,v 1.37 2000/11/16 17:31:53 greenrd Exp $ --
  +/*-- $Id: Engine.java,v 1.38 2000/11/20 01:43:53 greenrd Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -75,7 +75,7 @@
    *
    * @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a>
    * @author <a href="mailto:[EMAIL PROTECTED]">Robin Green</a>
  - * @version $Revision: 1.37 $ $Date: 2000/11/16 17:31:53 $
  + * @version $Revision: 1.38 $ $Date: 2000/11/20 01:43:53 $
    */
   
   public class Engine implements Defaults {
  @@ -319,7 +319,9 @@
                   }
               }
   
  -            if (page == null) {
  +            boolean wasInCache = (page != null);
  +
  +            if (!wasInCache) {
   
                   // the page was not found in the cache or the cache was
                   // disabled, we need to process it
  @@ -394,7 +396,7 @@
                               page.setContentType(formatter.getMIMEType());
                           }
   
  -                        // cache the created page.
  +                        // cache the created page, if it is cacheable
                           cache.setPage(page, request);
   
                           // page is done without memory errors so exit the 
loop
  @@ -425,8 +427,12 @@
                   response.setContentType(page.getContentType());
   
                   // set the Last-Modified header if this option is enabled in 
cocoon.properties
  +                // and the request has been cached
                   if (LASTMODIFIED) {
  -                   response.setDateHeader ("Last-Modified", 
cache.getLastModified (request));
  +                   long lastMod = cache.getLastModified (request);
  +                   if (lastMod > -1) {
  +                      response.setDateHeader ("Last-Modified", lastMod);
  +                   }
                   }
   
                   // get the output writer
  @@ -441,7 +447,7 @@
                   if (VERBOSE && (page.isText()) && 
!"HEAD".equals(request.getMethod())) {
                       time = System.currentTimeMillis() - time;
                       out.println("<!-- This page was served "
  -                        + (page.isCached() ? "from cache " : "")
  +                        + (wasInCache ? "from cache " : "")
                           + "in " + time + " milliseconds by "
                           + Cocoon.version() + " -->");
                       //out.println("<!-- free memory: " + 
Runtime.getRuntime().freeMemory() + " -->");
  
  
  
  1.4       +10 -4     
xml-cocoon/src/org/apache/cocoon/formatter/AbstractFormatter.java
  
  Index: AbstractFormatter.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon/src/org/apache/cocoon/formatter/AbstractFormatter.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- AbstractFormatter.java    2000/04/04 11:11:16     1.3
  +++ AbstractFormatter.java    2000/11/20 01:43:54     1.4
  @@ -1,4 +1,4 @@
  -/*-- $Id: AbstractFormatter.java,v 1.3 2000/04/04 11:11:16 stefano Exp $ -- 
  +/*-- $Id: AbstractFormatter.java,v 1.4 2000/11/20 01:43:54 greenrd Exp $ -- 
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -55,13 +55,15 @@
   import org.w3c.dom.*;
   import org.apache.xml.serialize.*;
   import org.apache.cocoon.framework.*;
  +import javax.servlet.http.HttpServletRequest;
   
   /**
    * @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a>
  - * @version $Revision: 1.3 $ $Date: 2000/04/04 11:11:16 $
  + * @version $Revision: 1.4 $ $Date: 2000/11/20 01:43:54 $
    */
   
  -public abstract class AbstractFormatter implements Configurable, Formatter, 
Status {
  +public abstract class AbstractFormatter 
  +implements Configurable, Formatter, Status, Cacheable {
    
       protected String statusMessage = "Abstract Formatter";
       protected String MIMEtype;
  @@ -160,4 +162,8 @@
           message.append("<br>");
           return message.toString();
       }       
  -}
  \ No newline at end of file
  +
  +    public boolean isCacheable (HttpServletRequest request) {
  +        return true;
  +    }
  +}
  
  
  
  1.5       +48 -12    xml-cocoon/src/org/apache/cocoon/framework/Page.java
  
  Index: Page.java
  ===================================================================
  RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/framework/Page.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Page.java 2000/02/13 18:29:22     1.4
  +++ Page.java 2000/11/20 01:43:54     1.5
  @@ -1,4 +1,4 @@
  -/*-- $Id: Page.java,v 1.4 2000/02/13 18:29:22 stefano Exp $ -- 
  +/*-- $Id: Page.java,v 1.5 2000/11/20 01:43:54 greenrd Exp $ -- 
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -51,33 +51,35 @@
   package org.apache.cocoon.framework;
   
   import java.util.*;
  +import javax.servlet.http.HttpServletRequest;
   import org.w3c.dom.*;
   
   /**
    * The Page wrapper class.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a>
  - * @version $Revision: 1.4 $ $Date: 2000/02/13 18:29:22 $
  + * @version $Revision: 1.5 $ $Date: 2000/11/20 01:43:54 $
    */
   
  -public class Page implements java.io.Serializable {
  +public class Page implements java.io.Serializable, Changeable, Cacheable {
        
  -     private String content = "text/xml";
  -     private String contentType;
  +    private String content = "text/xml";
  +    private String contentType;
  +
       private boolean cached = false;
       private Vector changeables = new Vector(3);
   
  -     public String getContent() {
  -             return this.content;
  -     }
  +    public String getContent() {
  +     return this.content;
  +    }
       
       public void setContent(String content) {
           this.content = content;
       }
        
  -     public String getContentType() {
  -             return this.contentType;
  -     }
  +    public String getContentType() {
  +     return this.contentType;
  +    }
   
       public void setContentType(String type) {
           if (type != null) this.contentType = type;
  @@ -98,8 +100,42 @@
       public boolean isCached() {
           return cached;
       }
  +
  +    public boolean hasChanged (Object context) {
  +        HttpServletRequest request = (HttpServletRequest) context;
  +
  +        Enumeration e = getChangeables();
  +        while (e.hasMoreElements()) {
  +            Changeable c = (Changeable) e.nextElement();
  +            if (c.hasChanged (request)) {
  +                return true;
  +            }
  +        }
  +        return false;
  +    }
  +
  +    public boolean isCacheable (HttpServletRequest request) {
  +
  +        // Certain types of requests should never be cached
  +        // Surprisingly, according to HTTP 1.1 spec, POST is
  +        // not one of them!
  +        String method = request.getMethod ();
  +        if (method.equals ("OPTIONS") || method.equals ("PUT") ||
  +            method.equals ("DELETE") || method.equals ("TRACE"))
  +            return false;
  +
  +        Enumeration e = getChangeables();
  +        while (e.hasMoreElements()) {
  +            Object x = e.nextElement ();
  +            if (!(x instanceof Cacheable)) return false;
  +
  +            Cacheable c = (Cacheable) x;
  +            if (!c.isCacheable(request)) return false;
  +        }
  +        return true;
  +    }
       
       public void setCached(boolean cached) {
           this.cached = cached;
       }
  -}
  \ No newline at end of file
  +}
  
  
  
  1.1                  xml-cocoon/src/org/apache/cocoon/framework/Cacheable.java
  
  Index: Cacheable.java
  ===================================================================
  /*-- $Id: Cacheable.java,v 1.1 2000/11/20 01:43:54 greenrd Exp $ -- 
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
   
   Copyright (C) @year@ The Apache Software Foundation. All rights reserved.
   
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
   
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
   
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
   
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
   
   4. The names "Cocoon" and  "Apache Software Foundation"  must not be used to
      endorse  or promote  products derived  from this  software without  prior
      written permission. For written permission, please contact
      [EMAIL PROTECTED]
   
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
   
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache 
   Software Foundation, please see <http://www.apache.org/>.
   
   */
  package org.apache.cocoon.framework;
  
  import javax.servlet.http.HttpServletRequest;
  
  /**
   * If a Component does not implement this interface, any requests using
   * this Component will never be cached. Note that AbstractFormatter
   * and XSPPage automatically implement this interface.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]">Robin Green</a>
   * @version $Revision: 1.1 $ $Date: 2000/11/20 01:43:54 $
   */
  
  public interface Cacheable {
  
    /** Returns whether this request is suitable for cacheing. */
    public boolean isCacheable (HttpServletRequest request);
  }
  
  
  
  1.19      +7 -2      
xml-cocoon/src/org/apache/cocoon/processor/xinclude/XIncludeProcessor.java
  
  Index: XIncludeProcessor.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon/src/org/apache/cocoon/processor/xinclude/XIncludeProcessor.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- XIncludeProcessor.java    2000/11/15 05:20:00     1.18
  +++ XIncludeProcessor.java    2000/11/20 01:43:55     1.19
  @@ -78,6 +78,7 @@
   import org.apache.cocoon.xml.util.XPathAPI;
   import org.apache.cocoon.framework.Status;
   import org.apache.cocoon.framework.AbstractActor;
  +import org.apache.cocoon.framework.Cacheable;
   import org.apache.cocoon.framework.Director;
   import org.apache.cocoon.framework.Monitor;
   import org.apache.cocoon.processor.Processor;
  @@ -101,9 +102,9 @@
    * a terrible wasteful of memory.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]">Donald Ball</a>
  - * @version CVS $Revision: 1.18 $ $Date: 2000/11/15 05:20:00 $ $Author: 
balld $
  + * @version CVS $Revision: 1.19 $ $Date: 2000/11/20 01:43:55 $ $Author: 
greenrd $
    */
  -public class XIncludeProcessor extends AbstractActor implements Processor, 
Status {
  +public class XIncludeProcessor extends AbstractActor implements Processor, 
Status, Cacheable {
   
        protected boolean debug = false;
   
  @@ -151,6 +152,10 @@
                }
                return false;
        }
  +
  +        public boolean isCacheable(HttpServletRequest request) {
  +               return true;
  +        }
   
   class XIncludeElement {
   
  
  
  
  1.17      +7 -3      
xml-cocoon/src/org/apache/cocoon/processor/xslt/XSLTProcessor.java
  
  Index: XSLTProcessor.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon/src/org/apache/cocoon/processor/xslt/XSLTProcessor.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- XSLTProcessor.java        2000/07/21 23:55:04     1.16
  +++ XSLTProcessor.java        2000/11/20 01:43:55     1.17
  @@ -1,4 +1,4 @@
  -/*-- $Id: XSLTProcessor.java,v 1.16 2000/07/21 23:55:04 stefano Exp $ --
  +/*-- $Id: XSLTProcessor.java,v 1.17 2000/11/20 01:43:55 greenrd Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -73,10 +73,10 @@
    * This class implements an XSLT processor.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a>
  - * @version $Revision: 1.16 $ $Date: 2000/07/21 23:55:04 $
  + * @version $Revision: 1.17 $ $Date: 2000/11/20 01:43:55 $
    */
   
  -public class XSLTProcessor implements Actor, Processor, Status, Defaults {
  +public class XSLTProcessor implements Actor, Processor, Status, Defaults, 
Cacheable {
   
       private Monitor monitor = new Monitor(10);
   
  @@ -225,6 +225,10 @@
   
       public boolean hasChanged(Object context) {
           return this.monitor.hasChanged(Utils.encode((HttpServletRequest) 
context));
  +    }
  +
  +    public boolean isCacheable(HttpServletRequest request) {
  +        return true;
       }
   
       public String getStatus() {
  
  
  
  1.21      +6 -0      
xml-cocoon/src/org/apache/cocoon/processor/xsp/xsp-java.xsl
  
  Index: xsp-java.xsl
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon/src/org/apache/cocoon/processor/xsp/xsp-java.xsl,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- xsp-java.xsl      2000/09/16 19:06:48     1.20
  +++ xsp-java.xsl      2000/11/20 01:43:56     1.21
  @@ -93,6 +93,12 @@
         /* User Class Declarations */
         <xsl:apply-templates select="xsp:logic" />
   
  +      <xsl:if test="xsp:structure/xsp:cacheable">
  +        public boolean isCacheable (HttpServletRequest request) {
  +          return true;
  +        }
  +      </xsl:if>
  +
         public void populateDocument(
           HttpServletRequest request,
           HttpServletResponse response,
  
  
  
  1.8       +11 -3     
xml-cocoon/src/org/apache/cocoon/processor/xsp/XSPPage.java
  
  Index: XSPPage.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon/src/org/apache/cocoon/processor/xsp/XSPPage.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- XSPPage.java      2000/09/17 14:31:28     1.7
  +++ XSPPage.java      2000/11/20 01:43:56     1.8
  @@ -1,4 +1,4 @@
  -/*-- $Id: XSPPage.java,v 1.7 2000/09/17 14:31:28 greenrd Exp $ -- 
  +/*-- $Id: XSPPage.java,v 1.8 2000/11/20 01:43:56 greenrd Exp $ -- 
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -63,9 +63,9 @@
   
   /**
    * @author <a href="mailto:[EMAIL PROTECTED]">Ricardo Rocha</a>
  - * @version $Revision: 1.7 $ $Date: 2000/09/17 14:31:28 $
  + * @version $Revision: 1.8 $ $Date: 2000/11/20 01:43:56 $
    */
  -public abstract class XSPPage extends AbstractProducer {
  +public abstract class XSPPage extends AbstractProducer implements Cacheable {
     protected Parser xspParser;
     protected ServletContext servletContext;
     protected XSPGlobal global;
  @@ -103,6 +103,14 @@
       HttpServletResponse response,
       Document document
     ) throws Exception;
  +
  +  /**
  +   * For backward repository compatibility when upgrading to Cocoon 1.8.1
  +   * from an earlier version.
  +   */
  +  public boolean isCacheable (HttpServletRequest request) {
  +    return false;
  +  }
   
     // <xsp:expr> methods
     protected Text xspExpr(char v, Document factory) {
  
  
  
  1.30      +37 -16    
xml-cocoon/src/org/apache/cocoon/processor/xsp/XSPProcessor.java
  
  Index: XSPProcessor.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon/src/org/apache/cocoon/processor/xsp/XSPProcessor.java,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- XSPProcessor.java 2000/11/15 18:33:32     1.29
  +++ XSPProcessor.java 2000/11/20 01:43:57     1.30
  @@ -1,4 +1,4 @@
  -/*-- $Id: XSPProcessor.java,v 1.29 2000/11/15 18:33:32 greenrd Exp $ --
  +/*-- $Id: XSPProcessor.java,v 1.30 2000/11/20 01:43:57 greenrd Exp $ --
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -78,10 +78,10 @@
    * This class implements the XSP engine.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]">Ricardo Rocha</a>
  - * @version $Revision: 1.29 $ $Date: 2000/11/15 18:33:32 $
  + * @version $Revision: 1.30 $ $Date: 2000/11/20 01:43:57 $
    */
   public class XSPProcessor extends AbstractActor
  -  implements Processor, Configurable, Status
  +  implements Processor, Configurable, Status, Cacheable
   {
     public static final String DEFAULT_LANGUAGE = "java";
     public static final String LOGICSHEET_PI = "xml-logicsheet";
  @@ -331,17 +331,14 @@
       HttpServletResponse response =
         (HttpServletResponse) parameters.get("response");
   
  +    // XXX: This is a mess - keys all over the place! - RDG
  +
       // Determine source document's absolute pathname
       String filename = Utils.getBasename(request, servletContext);
  -
       File sourceFile = new File(filename);
  -    try {
  -      filename = sourceFile.getCanonicalPath();
  -    } catch (IOException e) {
  -      filename = sourceFile.getAbsolutePath();
  -    }
  +    filename = getStoreKey (request);
   
  -    // Get page from Cocoon cache
  +    // Get page from Cocoon store
       PageEntry pageEntry = (PageEntry) this.store.get(filename);
   
       // New page?
  @@ -374,7 +371,7 @@
         this.store.hold(filename, pageEntry);
       }
   
  -    // Get page from Cocoon cache AGAIN to ensure proper synchronization
  +    // Get page from Cocoon store AGAIN to ensure proper synchronization
       pageEntry = (PageEntry) this.store.get(filename);
   
       synchronized (pageEntry) {
  @@ -619,21 +616,32 @@
       return this.global;
     }
   
  -  public boolean hasChanged(Object context) {
  -    if (!(context instanceof HttpServletRequest)) return true; // Can't 
interpret context
  +  protected String getStoreKey (Object context) {
  +    if (!(context instanceof HttpServletRequest)) {
  +      return null; // can't interpret context
  +    }
   
       HttpServletRequest request = (HttpServletRequest) context;
  + 
  +    // Determine source document's absolute pathname
       String filename = Utils.getBasename(request, servletContext);
  -
       File sourceFile = new File(filename);
       try {
  -      filename = sourceFile.getCanonicalPath();
  +      return sourceFile.getCanonicalPath();
       } catch (IOException e) {
  -      filename = sourceFile.getAbsolutePath();
  +      return sourceFile.getAbsolutePath();
       }
  +  }
   
  -    // Get page from Cocoon cache
  -    PageEntry pageEntry = (PageEntry) this.store.get(filename);
  +  protected PageEntry getPageEntry (Object context) {
  +    String storeKey = getStoreKey (context);
  +    if (storeKey == null) return null;
  +    return (PageEntry) store.get (storeKey);
  +  }
  +
  +  public boolean hasChanged(Object context) {
  +    // Get page from Cocoon store
  +    PageEntry pageEntry = getPageEntry (context);
   
       // New page?
       if (pageEntry == null) return true;
  @@ -643,6 +651,18 @@
       return pageEntry.getPage().hasChanged(context);
     }
   
  +  public boolean isCacheable(HttpServletRequest request) {
  +    // Get page from Cocoon store
  +    PageEntry pageEntry = getPageEntry (request);
  +
  +    // New page?
  +    if (pageEntry == null) return true;
  +
  +    // NOT pageEntry.isCacheable ()! We are calling the isCacheable method
  +    // of the XSP page itself.
  +    return pageEntry.getPage().isCacheable(request);
  +  }
  +
     public String getStatus() {
       return "eXtensible Server Pages Processor";
     }
  @@ -676,6 +696,7 @@
         return this.logicsheets;
       }
   
  +    /** Does the page need recompiling? */
       public boolean hasChanged() throws Exception {
         if (
           !this.target.exists() ||
  
  
  
  1.10      +7 -3      
xml-cocoon/src/org/apache/cocoon/producer/ProducerFromFile.java
  
  Index: ProducerFromFile.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon/src/org/apache/cocoon/producer/ProducerFromFile.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- ProducerFromFile.java     2000/05/06 11:13:53     1.9
  +++ ProducerFromFile.java     2000/11/20 01:43:59     1.10
  @@ -1,4 +1,4 @@
  -/*-- $Id: ProducerFromFile.java,v 1.9 2000/05/06 11:13:53 stefano Exp $ -- 
  +/*-- $Id: ProducerFromFile.java,v 1.10 2000/11/20 01:43:59 greenrd Exp $ -- 
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -65,10 +65,10 @@
    * based on its tranlated path.
    * 
    * @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a>
  - * @version $Revision: 1.9 $ $Date: 2000/05/06 11:13:53 $
  + * @version $Revision: 1.10 $ $Date: 2000/11/20 01:43:59 $
    */
   
  -public class ProducerFromFile extends AbstractProducer implements Status {
  +public class ProducerFromFile extends AbstractProducer implements Status, 
Cacheable {
       
       private Monitor monitor = new Monitor(10);
   
  @@ -88,6 +88,10 @@
       
       public boolean hasChanged(Object context) {
           return this.monitor.hasChanged(Utils.encode((HttpServletRequest) 
context));
  +    }
  +
  +    public boolean isCacheable(HttpServletRequest request) {
  +        return true;
       }
       
       public String getStatus() {
  
  
  
  1.21      +1 -0      xml-cocoon/xdocs/docs-book.xml
  
  Index: docs-book.xml
  ===================================================================
  RCS file: /home/cvs/xml-cocoon/xdocs/docs-book.xml,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- docs-book.xml     2000/11/13 20:52:51     1.20
  +++ docs-book.xml     2000/11/20 01:44:00     1.21
  @@ -12,6 +12,7 @@
     <page id="infrastructure" label="Infrastructure" 
source="infrastructure.xml"/>
     <page id="guide" label="User Guide" source="guide.xml"/>
     <page id="dynamic" label="Dynamic XML" source="dynamic.xml"/>
  +  <page id="caching" label="Caching" source="caching.xml"/>
     <page id="how-it-works" label="How it works" source="how-it-works.xml"/>
     <external label="XML Links" 
href="http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/"/>
   <separator/>
  
  
  
  1.22      +1 -0      xml-cocoon/xdocs/site-book.xml
  
  Index: site-book.xml
  ===================================================================
  RCS file: /home/cvs/xml-cocoon/xdocs/site-book.xml,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- site-book.xml     2000/11/13 20:52:51     1.21
  +++ site-book.xml     2000/11/20 01:44:00     1.22
  @@ -16,6 +16,7 @@
     <page id="infrastructure" label="Infrastructure" 
source="infrastructure.xml"/>
     <page id="guide" label="User Guide" source="guide.xml"/>
     <page id="dynamic" label="Dynamic XML" source="dynamic.xml"/>
  +  <page id="caching" label="Caching" source="caching.xml"/>
     <page id="how-it-works" label="How it works" source="how-it-works.xml"/>
     <external label="XML Links" 
href="http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/"/> 
   <separator/>
  
  
  
  1.1                  xml-cocoon/xdocs/caching.xml
  
  Index: caching.xml
  ===================================================================
  <?xml version="1.0"?>
  <!DOCTYPE document SYSTEM "./dtd/document-v10.dtd">
  <document>
   <header>
    <title>Cocoon Caching</title>
    <authors>
     <person name="Robin Green" email="[EMAIL PROTECTED]"/>
    </authors>
   </header>
  <body>
   <s1 title="A Brief Guide to the Cocoon Cache System">
    <p>
     The Cocoon cache system started off clean, simple, and easy to understand.
     However, unfortunately, it has outstripped its original design, and there
     are now various confusing aspects to it. This document does not attempt to
     be an exhaustive guide to Cocoon caching, but attempts to briefly document
     the most important aspects. A more comprehensive version may be written a
     later time - and remember, we're always 
     <connect href="contrib.xml">looking for volunteers</connect> to write
     documentation!
    </p>
  
    <p>
     Please read the comments in <code>cocoon.properties</code> for an
     explanation of the global caching parameters that Cocoon accepts.
    </p>
  
    <s2 title="What is cached and what is not?">
  
     <p>Currently, in Cocoon 1.x, the main result
      that is cached is the final output (usually HTML) of the request.
      Although a few other things are cached (such as in-memory representations
      of stylesheets and logicsheets) these are largely transparent to the 
Cocoon
      developer. In other words, the results of each stage in the pipeline
      are <em>not</em> cached.
     </p>
  
     <p>
      Various Cocoon components have different behaviours with regard to 
caching.
      Some components disable caching for all requests that use them; others
      flush a page from the cache and regenerate it under certain conditions.
      As per the HTTP 1.1 spec, certain request types
      such as PUT are never cached under any circumstances (however, POST is
      not one of these types - although 99% of the time it is not advisable to
      cache a POST request, it is possible to do so.)
     </p>
   
     <note>This document is accurate with respect to Cocoon 1.8.1. Older and
      newer versions may behave differently.</note>
  
     <p>
      In the table below, if any component being used by a request disables 
caching,
      caching is disabled for that request. If any component being used by a 
request
      invalidates the cache, the cached copy of that request is invalidated and 
removed.
     </p>
  
     <table>
      <tr>
       <th>Component</th>
       <th>Component Type</th>
       <th>Disables Caching For Affected Requests?</th>
       <th>Invalidates Cache?</th>
      </tr>
      <tr>
       <td>ProducerFromFile</td>
       <td>Producer (default)</td>
       <td>Never</td>
       <td>When file changes</td>
      </tr>
      <tr>
       <td>DCP</td>
       <td>Processor</td>
       <td>Always</td>
       <td>n/a</td>
      </tr>
      <tr>
       <td>LDAP</td>
       <td>Processor</td>
       <td>Always</td>
       <td>n/a</td>
      </tr>
      <tr>
       <td>SQL</td>
       <td>Processor</td>
       <td>Always</td>
       <td>n/a</td>
      </tr>
      <tr>
       <td>XInclude</td>
       <td>Processor</td>
       <td>Never</td>
       <td>When included file changes(?)</td>
      </tr>
      <tr>
       <td>XSLT</td>
       <td>Processor</td>
       <td>Never</td>
       <td>When stylesheet changes. NOTE: The caching behaviour of
        the XSLT document() function is not specified in the XSLT 1.0
        specification, so we recommend an alternative (e.g. 
        the more powerful XInclude)
        unless you don't care about caching.</td>
      </tr>
      <tr>
       <td>XSP</td>
       <td>"Processor"/"Producer"</td>
       <td>By default, yes; however, XSP pages can override this by putting
        <code>&lt;xsp:cacheable/&gt;</code> within <code>&lt;xsp:structure&gt;
        </code> (see XSP documentation.)
       </td>
       <td>Not applicable if xsp:cacheable tag is missing, since page will
        never be cached. Otherwise, define the <code>public boolean hasChanged
        (Object context)</code> method to define cache invalidation behaviour.
        Always returning <code>false</code> will never invalidate, for example. 
        The context object is currently a HttpServletRequest. Default behaviour
        is always invalidate. (see XSP documentation.)
       </td>
      </tr>
      <tr>
       <td>All Cocoon-supplied Formatters</td>
       <td>Formatters</td>
       <td>Never</td>
       <td>Never</td>
      </tr>
     </table>
    </s2>
  
    <s2 title="The XSP Repository">
     <p>
      The XSP repository where compiled XSP pages are stored
      (see <code>cocoon.properties</code>) is often thought of as a cache, but
      strictly speaking it is not. At the moment, all commonly available Java 
compilers
      such as <code>javac</code> and <code>jikes</code> will only read and 
write files,
      not in-memory objects. Thus, writing <code>.java</code> and 
<code>.class</code>
      files to disk is essential.
     </p>
     <p>
      It does not really make sense to say that XSP pages are compiled once, 
and then
      "cached" thereafter so that they do not have to be used again. While this 
is 
      approximately true, XSP generated classes are just normal classes - they 
remain
      in memory after use. No caching mechanism is needed.
     </p>
     <p>
      Although XSP is implemented in Cocoon 1 as a Processor, it is really more 
like a
      Producer, because it ignores whether its input has changed. It was 
written based
      on the assumption that it would be fed directly from a ProducerFromFile, 
and nothing
      else. Thus XSPProcessor will <strong>not</strong> correctly handle 
dynamic input.
      This is also why you cannot use XSP twice for one request  
      (unless you use something like XInclude).
     </p>
     <note>
      This anomaly has been corrected in Cocoon 2, where XSP is a Generator.
     </note>
    </s2>
  
    <s2 title="What determines request equivalence?">
     <p>Cocoon uses the following factors to decide if a request is equivalent 
to a
      previous one. Only if all factors are identical will the cached copy (if 
any)
      be used.</p>
  
     <ul>
      <li>HTTP User Agent string (identifies the browser)</li>
      <li>Scheme (HTTP, HTTPS, etc.)</li>
      <li>Server name</li>
      <li>Port</li>
      <li>Rest of URI, including query string</li>
     </ul>
    </s2>
  
    <s2 title="Example of caching dynamic content - Why Bother?">
     <p>Sometimes there is no point, and it can even cause bugs. Hence,
      all dynamic content, by default, is not cached.
      However, because Cocoon caches based on the <strong>query string</strong>,
      as mentioned above, it can be useful to override this.
     </p>
  
     <p>Suppose you are presenting a large web directory with Cocoon.
      All of the directory content is served from a robust back-end database.
      Since the root of the directory (?node=1) is requested so frequently, it
      makes sense to cache the transformed representation (HTML) of this 
      and other popular nodes. Assuming you are using
      XSP, you can simply declare <code>&lt;xsp:cacheable/&gt;</code> and the
      following method:
     </p>
  
     <source>
       public boolean hasChanged (Object context) {
         return false; // to cache everything and leave
         // memory management up to Cocoon
  
         // or
         try {
           return Integer.parseInt 
             (((HttpServletRequest) context).getParameter ("node")) 
             &lt; 50; // only cache the most important 50 nodes.
         }
         catch (NumberFormatException ex) {
           // error pages don't change
           return false;
         } 
       }
     </source>
    </s2>
  
    <s2 title="Advanced Cache Control">
     <p>
      If writing your own Producer or Processor, implement the
      <code>org.apache.cocoon.framework.Cacheable</code> and
      <code>org.apache.cocoon.framework.Changeable</code> interfaces to
      define custom caching behaviour. The same degree of control is also
      available to XSP pages - see table above.
     </p>
    </s2>
   </s1>
  </body>
  </document>
  
  
  

Reply via email to