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><xsp:cacheable/></code> within <code><xsp:structure>
</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><xsp:cacheable/></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"))
< 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>