You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by cz...@apache.org on 2001/04/20 13:27:27 UTC
cvs commit: xml-cocoon/src/org/apache/cocoon/reading AbstractReader.java Reader.java ResourceReader.java
cziegeler 01/04/20 04:27:26
Modified: src/org/apache/cocoon/caching Tag: xml-cocoon2
CachingOutputStream.java
src/org/apache/cocoon/components/pipeline Tag: xml-cocoon2
AbstractStreamPipeline.java
CachingStreamPipeline.java
src/org/apache/cocoon/environment Tag: xml-cocoon2
AbstractEnvironment.java Environment.java
src/org/apache/cocoon/environment/http Tag: xml-cocoon2
HttpEnvironment.java
src/org/apache/cocoon/reading Tag: xml-cocoon2
AbstractReader.java Reader.java ResourceReader.java
Log:
1. Improved caching of StreamPipelines
2. Refactured the ResourceReader
3. The StreamPipeline sets using the Environment the
http headers for read resources
Revision Changes Path
No revision
No revision
1.1.2.3 +30 -10 xml-cocoon/src/org/apache/cocoon/caching/Attic/CachingOutputStream.java
Index: CachingOutputStream.java
===================================================================
RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/caching/Attic/CachingOutputStream.java,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -u -r1.1.2.2 -r1.1.2.3
--- CachingOutputStream.java 2001/04/17 15:32:56 1.1.2.2
+++ CachingOutputStream.java 2001/04/20 11:27:01 1.1.2.3
@@ -7,7 +7,6 @@
*****************************************************************************/
package org.apache.cocoon.caching;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -17,47 +16,68 @@
* TeeOutputStream.
*
* @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
- * @version CVS $Revision: 1.1.2.2 $ $Date: 2001/04/17 15:32:56 $
+ * @version CVS $Revision: 1.1.2.3 $ $Date: 2001/04/20 11:27:01 $
*/
public final class CachingOutputStream
extends OutputStream {
private OutputStream receiver;
- private ByteArrayOutputStream baOutputStream;
+ /** The buffer for the compile xml byte stream. */
+ private byte buf[];
+
+ /** The number of valid bytes in the buffer. */
+ private int bufCount;
+
public CachingOutputStream(OutputStream os) {
this.receiver = os;
- this.baOutputStream = new ByteArrayOutputStream();
+ this.buf = new byte[1024];
+ this.bufCount = 0;
}
public byte[] getContent() {
- return this.baOutputStream.toByteArray();
+ byte newbuf[] = new byte[this.bufCount];
+ System.arraycopy(this.buf, 0, newbuf, 0, this.bufCount);
+ return newbuf;
}
public void write(int b) throws IOException {
this.receiver.write(b);
- this.baOutputStream.write(b);
+ int newcount = this.bufCount + 1;
+ if (newcount > this.buf.length) {
+ byte newbuf[] = new byte[Math.max(this.buf.length << 1, newcount)];
+ System.arraycopy(this.buf, 0, newbuf, 0, this.bufCount);
+ this.buf = newbuf;
+ }
+ this.buf[this.bufCount] = (byte)b;
+ this.bufCount = newcount;
}
public void write( byte b[] ) throws IOException {
this.receiver.write(b);
- this.baOutputStream.write(b);
+ this.write(b, 0, b.length);
}
public void write(byte b[], int off, int len) throws IOException {
this.receiver.write(b, off, len);
- this.baOutputStream.write(b, off, len);
+ if (len == 0) return;
+ int newcount = this.bufCount + len;
+ if (newcount > this.buf.length) {
+ byte newbuf[] = new byte[Math.max(this.buf.length << 1, newcount)];
+ System.arraycopy(this.buf, 0, newbuf, 0, this.bufCount);
+ this.buf = newbuf;
+ }
+ System.arraycopy(b, off, this.buf, this.bufCount, len);
+ this.bufCount = newcount;
}
public void flush() throws IOException {
this.receiver.flush();
- this.baOutputStream.flush();
}
public void close() throws IOException {
this.receiver.close();
- this.baOutputStream.close();
}
No revision
No revision
1.1.2.4 +11 -1 xml-cocoon/src/org/apache/cocoon/components/pipeline/Attic/AbstractStreamPipeline.java
Index: AbstractStreamPipeline.java
===================================================================
RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/components/pipeline/Attic/AbstractStreamPipeline.java,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -u -r1.1.2.3 -r1.1.2.4
--- AbstractStreamPipeline.java 2001/04/19 11:30:38 1.1.2.3
+++ AbstractStreamPipeline.java 2001/04/20 11:27:05 1.1.2.4
@@ -38,7 +38,7 @@
* resource
* </UL>
* @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a>
- * @version CVS $Revision: 1.1.2.3 $ $Date: 2001/04/19 11:30:38 $
+ * @version CVS $Revision: 1.1.2.4 $ $Date: 2001/04/20 11:27:05 $
*/
public abstract class AbstractStreamPipeline extends AbstractLoggable implements StreamPipeline, Disposable {
protected EventPipeline eventPipeline;
@@ -160,6 +160,16 @@
} else {
environment.setContentType(this.sitemapReaderMimeType);
}
+ // has the read resource been modified?
+ long lastModified = this.reader.getLastModified();
+ if (lastModified != 0
+ && environment.isResponseModified(lastModified) == false) {
+
+ // environment supports this, so we are finished
+ environment.setResponseIsNotModified();
+ return true;
+ }
+
this.reader.setOutputStream(environment.getOutputStream());
int length = this.reader.generate();
if (length != 0) {
1.1.2.5 +14 -4 xml-cocoon/src/org/apache/cocoon/components/pipeline/Attic/CachingStreamPipeline.java
Index: CachingStreamPipeline.java
===================================================================
RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/components/pipeline/Attic/CachingStreamPipeline.java,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -u -r1.1.2.4 -r1.1.2.5
--- CachingStreamPipeline.java 2001/04/19 13:11:44 1.1.2.4
+++ CachingStreamPipeline.java 2001/04/20 11:27:06 1.1.2.5
@@ -46,7 +46,7 @@
* </ul>
*
* @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
- * @version CVS $Revision: 1.1.2.4 $ $Date: 2001/04/19 13:11:44 $
+ * @version CVS $Revision: 1.1.2.5 $ $Date: 2001/04/20 11:27:06 $
*/
public final class CachingStreamPipeline extends AbstractStreamPipeline {
@@ -93,7 +93,7 @@
protected boolean processReader(Environment environment)
throws ProcessingException {
- try
+ try
{
this.reader.setup((EntityResolver) environment,environment.getObjectModel(),readerSource,readerParam);
String mimeType = this.reader.getMimeType();
@@ -106,6 +106,16 @@
} else {
environment.setContentType(this.sitemapReaderMimeType);
}
+
+ // has the read resource been modified?
+ long lastModified = this.reader.getLastModified();
+ if (lastModified != 0
+ && environment.isResponseModified(lastModified) == false) {
+
+ // environment supports this, so we are finished
+ environment.setResponseIsNotModified();
+ return true;
+ }
} catch (SAXException e){
getLogger().debug("SAXException in ProcessReader", e);
@@ -161,7 +171,7 @@
}
if (valid == true) {
getLogger().debug("Using valid cached content.");
-
+
usedCache = true;
byte[] response = cachedObject.getResponse();
outputStream.write(response);
@@ -170,7 +180,7 @@
}
} else {
getLogger().debug("Cached content is invalid.");
-
+
// remove invalid cached object
this.streamCache.remove(pcKey);
cachedObject = null;
No revision
No revision
1.1.2.15 +20 -0 xml-cocoon/src/org/apache/cocoon/environment/Attic/AbstractEnvironment.java
Index: AbstractEnvironment.java
===================================================================
RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/environment/Attic/AbstractEnvironment.java,v
retrieving revision 1.1.2.14
retrieving revision 1.1.2.15
diff -u -r1.1.2.14 -r1.1.2.15
--- AbstractEnvironment.java 2001/04/19 11:30:42 1.1.2.14
+++ AbstractEnvironment.java 2001/04/20 11:27:10 1.1.2.15
@@ -202,4 +202,24 @@
this.uris.remove(this.uris.size()-1);
return uri;
}
+
+ /**
+ * Check if the response has been modified since the same
+ * "resource" was requested.
+ * The caller has to test if it is really the same "resource"
+ * which is requested.
+ * @result true if the response is modified or if the
+ * environment is not able to test it
+ */
+ public boolean isResponseModified(long lastModified) {
+ return true; // always modified
+ }
+
+ /**
+ * Mark the response as not modified.
+ */
+ public void setResponseIsNotModified() {
+ // does nothing
+ }
+
}
1.1.2.18 +15 -1 xml-cocoon/src/org/apache/cocoon/environment/Attic/Environment.java
Index: Environment.java
===================================================================
RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/environment/Attic/Environment.java,v
retrieving revision 1.1.2.17
retrieving revision 1.1.2.18
diff -u -r1.1.2.17 -r1.1.2.18
--- Environment.java 2001/04/19 11:30:42 1.1.2.17
+++ Environment.java 2001/04/20 11:27:11 1.1.2.18
@@ -20,7 +20,7 @@
* Base interface for an environment abstraction
*
* @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a>
- * @version CVS $Revision: 1.1.2.17 $ $Date: 2001/04/19 11:30:42 $
+ * @version CVS $Revision: 1.1.2.18 $ $Date: 2001/04/20 11:27:11 $
*/
public interface Environment extends EntityResolver {
@@ -85,5 +85,19 @@
*/
String popURI();
+ /**
+ * Check if the response has been modified since the same
+ * "resource" was requested.
+ * The caller has to test if it is really the same "resource"
+ * which is requested.
+ * @result true if the response is modified or if the
+ * environment is not able to test it
+ */
+ boolean isResponseModified(long lastModified);
+
+ /**
+ * Mark the response as not modified.
+ */
+ void setResponseIsNotModified();
}
No revision
No revision
1.1.2.24 +23 -0 xml-cocoon/src/org/apache/cocoon/environment/http/Attic/HttpEnvironment.java
Index: HttpEnvironment.java
===================================================================
RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/environment/http/Attic/HttpEnvironment.java,v
retrieving revision 1.1.2.23
retrieving revision 1.1.2.24
diff -u -r1.1.2.23 -r1.1.2.24
--- HttpEnvironment.java 2001/04/18 12:05:59 1.1.2.23
+++ HttpEnvironment.java 2001/04/20 11:27:18 1.1.2.24
@@ -124,4 +124,27 @@
public OutputStream getOutputStream() throws IOException {
return this.outputStream;
}
+
+ /**
+ * Check if the response has been modified since the same
+ * "resource" was requested.
+ * The caller has to test if it is really the same "resource"
+ * which is requested.
+ * @result true if the response is modified or if the
+ * environment is not able to test it
+ */
+ public boolean isResponseModified(long lastModified) {
+ long if_modified_since = this.request.getDateHeader("If-Modified-Since");
+
+ this.response.setDateHeader("Last-Modified", lastModified);
+ return (if_modified_since < lastModified);
+ }
+
+ /**
+ * Mark the response as not modified.
+ */
+ public void setResponseIsNotModified() {
+ this.response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ }
+
}
No revision
No revision
1.1.2.16 +9 -1 xml-cocoon/src/org/apache/cocoon/reading/Attic/AbstractReader.java
Index: AbstractReader.java
===================================================================
RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/reading/Attic/AbstractReader.java,v
retrieving revision 1.1.2.15
retrieving revision 1.1.2.16
diff -u -r1.1.2.15 -r1.1.2.16
--- AbstractReader.java 2001/04/18 16:56:53 1.1.2.15
+++ AbstractReader.java 2001/04/20 11:27:20 1.1.2.16
@@ -24,7 +24,7 @@
/**
*
* @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a>
- * @version CVS $Revision: 1.1.2.15 $ $Date: 2001/04/18 16:56:53 $
+ * @version CVS $Revision: 1.1.2.16 $ $Date: 2001/04/20 11:27:20 $
*/
public abstract class AbstractReader extends AbstractLoggable implements Reader, Recyclable {
/** The current <code>EntityResolver</code>. */
@@ -64,6 +64,14 @@
*/
public String getMimeType() {
return null;
+ }
+
+ /**
+ * @return the time the read source was last modified or 0 if it is not
+ * possible to detect
+ */
+ public long getLastModified() {
+ return 0;
}
/**
1.1.2.6 +6 -1 xml-cocoon/src/org/apache/cocoon/reading/Attic/Reader.java
Index: Reader.java
===================================================================
RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/reading/Attic/Reader.java,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -u -r1.1.2.5 -r1.1.2.6
--- Reader.java 2001/04/18 12:06:01 1.1.2.5
+++ Reader.java 2001/04/20 11:27:21 1.1.2.6
@@ -18,7 +18,7 @@
/**
*
* @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a>
- * @version CVS $Revision: 1.1.2.5 $ $Date: 2001/04/18 12:06:01 $
+ * @version CVS $Revision: 1.1.2.6 $ $Date: 2001/04/20 11:27:21 $
*/
public interface Reader extends SitemapModelComponent, SitemapOutputComponent {
@@ -30,4 +30,9 @@
int generate()
throws IOException, SAXException, ProcessingException;
+ /**
+ * @return the time the read source was last modified or 0 if it is not
+ * possible to detect
+ */
+ long getLastModified();
}
1.1.2.29 +67 -90 xml-cocoon/src/org/apache/cocoon/reading/Attic/ResourceReader.java
Index: ResourceReader.java
===================================================================
RCS file: /home/cvs/xml-cocoon/src/org/apache/cocoon/reading/Attic/ResourceReader.java,v
retrieving revision 1.1.2.28
retrieving revision 1.1.2.29
diff -u -r1.1.2.28 -r1.1.2.29
--- ResourceReader.java 2001/04/18 16:56:55 1.1.2.28
+++ ResourceReader.java 2001/04/20 11:27:22 1.1.2.29
@@ -45,7 +45,7 @@
/**
*
* @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a>
- * @version CVS $Revision: 1.1.2.28 $ $Date: 2001/04/18 16:56:55 $
+ * @version CVS $Revision: 1.1.2.29 $ $Date: 2001/04/20 11:27:22 $
*
* The <code>ResourceReader</code> component is used to serve binary data
* in a sitemap pipeline. It makes use of HTTP Headers to determine if
@@ -61,7 +61,7 @@
* </dd>
* </dl>
*/
-public class ResourceReader extends AbstractReader
+public class ResourceReader extends AbstractReader
implements Composer, Cacheable {
private ComponentManager manager;
@@ -69,19 +69,69 @@
/** The system ID of the input source */
private String systemID;
+
+ private InputStream inputStream;
+ private long inputLength;
+ private long lastModified;
+
/**
- * Setup the file generator.
+ * Setup the reader.
+ * The resource is opened to get an <code>InputStream</code>,
+ * the length and the last modification date
*/
public void setup(EntityResolver resolver, Map objectModel, String src, Parameters par)
throws ProcessingException, SAXException, IOException {
super.setup(resolver, objectModel, src, par);
this.systemID = resolver.resolveEntity(null, super.source).getSystemId();
+
+ URLFactory urlFactory = null;
+ try {
+ try {
+ urlFactory = (URLFactory) this.manager.lookup(Roles.URL_FACTORY);
+ } catch (Exception e) {
+ getLogger().error("cannot obtain the URLFactory", e);
+ throw new ProcessingException ("cannot obtain the URLFactory", e);
+ }
+ try {
+ if (this.source.indexOf(":/") != -1) {
+ URLConnection conn = urlFactory.getURL(this.source).openConnection();
+ this.lastModified = conn.getLastModified();
+ this.inputLength = conn.getContentLength();
+ this.inputStream = conn.getInputStream();
+ } else {
+ File file = new File(urlFactory.getURL(this.systemID).getFile());
+ this.lastModified = file.lastModified();
+ this.inputLength = file.length();
+ this.inputStream = new BufferedInputStream(new FileInputStream (file));
+ }
+ } catch (MalformedURLException mue) {
+ getLogger().error("ResourceReader: malformed source \"" + this.source + "\"", mue);
+ throw new ResourceNotFoundException ("ResourceReader: malformed source \""
+ +this.source+"\". ", mue);
+ }
+ } finally {
+ if (urlFactory != null) {
+ this.manager.release((Component)urlFactory);
+ }
+ }
}
public void compose (ComponentManager manager) {
this.manager = manager;
}
+ public void recycle() {
+ super.recycle();
+ if (this.inputStream != null) {
+ try {
+ this.inputStream.close();
+ } catch (IOException ioe) {
+ getLogger().debug("Received an IOException, assuming client severed connection on purpose");
+ }
+ this.inputStream = null;
+ }
+ }
+
/**
* Generate the unique key.
* This key must be unique inside the space of this component.
@@ -89,10 +139,7 @@
* @return The generated key hashes the src
*/
public long generateKey() {
- if (this.systemID.startsWith("file:") == true) {
- return HashUtil.hash(this.systemID);
- }
- return 0;
+ return HashUtil.hash(this.systemID);
}
/**
@@ -102,78 +149,24 @@
* component is currently not cacheable.
*/
public CacheValidity generateValidity() {
- if (this.systemID.startsWith("file:") == true) {
- File xmlFile = new File(this.systemID.substring("file:".length()));
- return new TimeStampCacheValidity(xmlFile.lastModified());
- }
- return null;
+ return new TimeStampCacheValidity(this.lastModified);
}
/**
+ * @return the time the read source was last modified or 0 if it is not
+ * possible to detect
+ */
+ public long getLastModified() {
+ return this.lastModified;
+ }
+
+ /**
* Generates the requested resource.
*/
public int generate() throws IOException, ProcessingException {
Request request = (Request) objectModel.get(Constants.REQUEST_OBJECT);
Response response = (Response) objectModel.get(Constants.RESPONSE_OBJECT);
- if (response == null) {
- throw new ProcessingException ("Missing a Response object in the objectModel");
- }
-
- if (request == null) {
- throw new ProcessingException ("Missing a Request object in the objectModel");
- }
-
- String src = null;
- File file = null;
- URL url = null;
- URLConnection conn = null;
- InputStream is = null;
- long len = 0;
-
- URLFactory urlFactory = null;
- try {
- try {
- urlFactory = (URLFactory) this.manager.lookup(Roles.URL_FACTORY);
- } catch (Exception e) {
- getLogger().error("cannot obtain the URLFactory", e);
- throw new ProcessingException ("cannot obtain the URLFactory", e);
- }
- if(this.source.indexOf(":/") != -1) {
- src = this.source;
- url = urlFactory.getURL (src);
- conn = url.openConnection();
-
- if (!modified (conn.getLastModified(), request, response)) {
- return 0;
- }
-
- len = conn.getContentLength();
- is = conn.getInputStream();
- } else {
- src = this.resolver.resolveEntity (null,this.source).getSystemId();
- url = urlFactory.getURL (src);
- file = new File (url.getFile());
-
- if (!modified (file.lastModified(), request, response)) {
- return 0;
- }
-
- len = file.length();
- is = new BufferedInputStream(new FileInputStream (file));
- }
- } catch (SAXException se) {
- getLogger().error("ResourceReader: error resolving source \"" + source + "\"", se);
- throw new ResourceNotFoundException ("ResourceReader: error resolving source \""
- +source+"\". ", se);
- } catch (MalformedURLException mue) {
- getLogger().error("ResourceReader: malformed source \"" + source + "\"", mue);
- throw new ResourceNotFoundException ("ResourceReader: malformed source \""
- +src+"\". ", mue);
- } finally {
- if(urlFactory != null) this.manager.release((Component) urlFactory);
- }
-
try {
long expires = parameters.getParameterAsInteger("expires", -1);
@@ -186,32 +179,16 @@
byte[] buffer = new byte[8192];
int length = -1;
- while ((length = is.read(buffer)) > -1) {
+ while ((length = this.inputStream.read(buffer)) > -1) {
out.write(buffer, 0, length);
}
- is.close();
+ this.inputStream.close();
+ this.inputStream = null;
out.flush();
} catch (IOException ioe) {
getLogger().debug("Received an IOException, assuming client severed connection on purpose");
}
- return (int)len;
- }
-
- /**
- * Checks if the file has been modified
- */
- private boolean modified (long lastModified, Request request, Response response) {
- response.setDateHeader("Last-Modified", lastModified);
- long if_modified_since = request.getDateHeader("if-modified-since");
- boolean isHttpResponse = response instanceof org.apache.cocoon.environment.http.HttpResponse;
-
- if (if_modified_since >= lastModified && isHttpResponse == true) {
- ((org.apache.cocoon.environment.http.HttpResponse)response).setStatus(
- javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED);
- }
-
- getLogger().debug("ResourceReader: resource has " + ((if_modified_since < lastModified) ? "" : "not ") + "been modified");
- return (if_modified_since < lastModified || isHttpResponse == false);
+ return (int)this.inputLength;
}
/**
----------------------------------------------------------------------
In case of troubles, e-mail: webmaster@xml.apache.org
To unsubscribe, e-mail: cocoon-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-cvs-help@xml.apache.org