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