You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by vg...@apache.org on 2005/10/04 16:39:07 UTC

svn commit: r293608 - in /cocoon/blocks/scratchpad/trunk: java/org/apache/cocoon/components/source/impl/ZipSource.java java/org/apache/cocoon/components/source/impl/ZipSourceFactory.java samples/sources/sitemap.xmap

Author: vgritsenko
Date: Tue Oct  4 07:38:53 2005
New Revision: 293608

URL: http://svn.apache.org/viewcvs?rev=293608&view=rev
Log:
changed zip: source url syntax to be same as for jar:
fixed memory leak

Modified:
    cocoon/blocks/scratchpad/trunk/java/org/apache/cocoon/components/source/impl/ZipSource.java
    cocoon/blocks/scratchpad/trunk/java/org/apache/cocoon/components/source/impl/ZipSourceFactory.java
    cocoon/blocks/scratchpad/trunk/samples/sources/sitemap.xmap

Modified: cocoon/blocks/scratchpad/trunk/java/org/apache/cocoon/components/source/impl/ZipSource.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/scratchpad/trunk/java/org/apache/cocoon/components/source/impl/ZipSource.java?rev=293608&r1=293607&r2=293608&view=diff
==============================================================================
--- cocoon/blocks/scratchpad/trunk/java/org/apache/cocoon/components/source/impl/ZipSource.java (original)
+++ cocoon/blocks/scratchpad/trunk/java/org/apache/cocoon/components/source/impl/ZipSource.java Tue Oct  4 07:38:53 2005
@@ -1,12 +1,12 @@
 /*
- * Copyright 1999-2004 The Apache Software Foundation.
- * 
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -27,104 +27,108 @@
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceNotFoundException;
 import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.source.SourceResolver;
 
 /**
-  * @author <a href="http://apache.org/~reinhard">Reinhard Poetz</a>
-  * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
-  * @version CVS $Id: ZipSource.java,v 1.2 2004/03/05 10:07:25 bdelacretaz Exp $
-  * @since 2.1.4 
-  */
-public class ZipSource extends AbstractLogEnabled implements Source {
+ * @author <a href="http://apache.org/~reinhard">Reinhard Poetz</a>
+ * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ * @version CVS $Id$
+ * @since 2.1.8
+ */
+public class ZipSource extends AbstractLogEnabled
+                       implements Source {
+
+    private String protocol;
+    private Source archive;
+    private String filePath;
 
-    Source archive;
-    String documentName;
 
-    public ZipSource(Source archive, String fileName) {
+    public ZipSource(String protocol, Source archive, String filePath) {
+        this.protocol = protocol;
         this.archive = archive;
-        this.documentName = fileName;
+        this.filePath = filePath;
+    }
+
+    private ZipEntry findEntry(ZipInputStream zipStream)
+    throws IOException {
+        ZipEntry entry;
+        while ((entry = zipStream.getNextEntry()) != null) {
+            if (entry.getName().equals(this.filePath)) {
+                return entry;
+            }
+            zipStream.closeEntry();
+        }
+
+        return null;
+    }
+
+    /* package access */
+    void dispose(SourceResolver resolver) {
+        resolver.release(this.archive);
+        this.archive = null;
     }
 
     public boolean exists() {
         if(!this.archive.exists()) {
             return false;
         }
+
         ZipInputStream zipStream = null;
-        ZipEntry document = null;
-        boolean found = false;
         try {
             zipStream = new ZipInputStream(this.archive.getInputStream());
-            do {
-                document = zipStream.getNextEntry();
-                if (document != null) {
-                    if (document.getName().equals(this.documentName)) {
-                        found = true;
-                    } else {
-                        zipStream.closeEntry();
-                    }
-                }
-            } while (document != null && found == false);
-        } catch(IOException ioe) {
+            return findEntry(zipStream) != null;
+        } catch (IOException e) {
             return false;
         } finally {
             try {
-                zipStream.close();
-            } catch (IOException ioe) {
-                this.getLogger().error("Error while closing ZipInputStream: " + this.documentName);
+                if (zipStream != null) {
+                    zipStream.close();
+                }
+            } catch (IOException e) {
+                getLogger().error("IOException while closing ZipInputStream: " + this.filePath);
             }
-        } 
-        return found;
+        }
     }
-    
+
     public InputStream getInputStream()
-        throws IOException, SourceNotFoundException {
+    throws IOException, SourceNotFoundException {
 
-        ZipInputStream zipStream =
-            new ZipInputStream(this.archive.getInputStream());
-        ZipEntry document = null;
-        boolean found = false;
-        do {
-            document = zipStream.getNextEntry();
-            if (document != null) {
-                if (document.getName().equals(this.documentName)) {
-                    found = true;
-                } else {
-                    // go to next entry
-                    zipStream.closeEntry();
-                }
+        ZipInputStream zipStream = new ZipInputStream(this.archive.getInputStream());
+        try {
+            ZipEntry entry = findEntry(zipStream);
+            if (entry == null) {
+                throw new SourceNotFoundException("File " + filePath + " is not found in the archive " +
+                                                  this.archive.getURI());
             }
-        } while (document != null && found == false);
 
-        if (document == null) {
-            throw new SourceNotFoundException(
-                "The document "
-                    + documentName
-                    + " is not in the archive "
-                    + this.archive.getURI());
-        }
+            // Now we will extract the document and write it into a byte array
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            byte[] buffer = new byte[8192];
+            int length;
+            while (zipStream.available() > 0) {
+                length = zipStream.read(buffer, 0, 8192);
+                if (length > 0) {
+                    baos.write(buffer, 0, length);
+                }
+            }
 
-        // now we will extract the document and write it into a byte array
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        byte[] buffer = new byte[8192];
-        int length = -1;
-        while (zipStream.available() > 0) {
-            length = zipStream.read(buffer, 0, 8192);
-            if (length > 0) {
-                baos.write(buffer, 0, length);
+            // Return an input stream
+            return new ByteArrayInputStream(baos.toByteArray());
+        } finally {
+            try {
+                zipStream.close();
+            } catch (IOException e) {
+                getLogger().error("IOException while closing ZipInputStream: " + this.filePath);
             }
         }
-        zipStream.close();
-        baos.flush();
-
-        // return an input stream
-        return new ByteArrayInputStream(baos.toByteArray());
     }
 
     public String getURI() {
-        return this.archive.getURI() + "/" + this.documentName;
+        return this.protocol + this.archive.getURI() + "!/" + this.filePath;
     }
 
     public String getScheme() {
-        return ZipSourceFactory.ZIP_SOURCE_SCHEME;
+        return this.protocol;
     }
 
     public SourceValidity getValidity() {
@@ -135,16 +139,35 @@
     }
 
     public String getMimeType() {
-        String ext = this.documentName.substring( this.documentName.lastIndexOf(".") );
-        return MIMEUtils.getMIMEType( ext );
+        String ext = this.filePath.substring(this.filePath.lastIndexOf("."));
+        return MIMEUtils.getMIMEType(ext);
     }
 
     public long getContentLength() {
+        ZipInputStream zipStream = null;
+        try {
+            zipStream = new ZipInputStream(this.archive.getInputStream());
+            ZipEntry entry = findEntry(zipStream);
+            if (entry != null) {
+                return entry.getSize();
+            }
+
+        } catch (IOException e) {
+            // Ignored
+        } finally {
+            try {
+                if (zipStream != null) {
+                    zipStream.close();
+                }
+            } catch (IOException e) {
+                getLogger().error("IOException while closing ZipInputStream: " + this.filePath);
+            }
+        }
+
         return -1;
     }
 
     public long getLastModified() {
         return this.archive.getLastModified();
     }
-
 }

Modified: cocoon/blocks/scratchpad/trunk/java/org/apache/cocoon/components/source/impl/ZipSourceFactory.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/scratchpad/trunk/java/org/apache/cocoon/components/source/impl/ZipSourceFactory.java?rev=293608&r1=293607&r2=293608&view=diff
==============================================================================
--- cocoon/blocks/scratchpad/trunk/java/org/apache/cocoon/components/source/impl/ZipSourceFactory.java (original)
+++ cocoon/blocks/scratchpad/trunk/java/org/apache/cocoon/components/source/impl/ZipSourceFactory.java Tue Oct  4 07:38:53 2005
@@ -1,12 +1,12 @@
 /*
- * Copyright 1999-2004 The Apache Software Foundation.
- * 
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -29,63 +29,82 @@
 import org.apache.excalibur.source.SourceFactory;
 import org.apache.excalibur.source.SourceResolver;
 
-
-/** Implementation of a {@link Source} that gets its content from
-  * and ZIP archive.
-  * 
-  * A ZIP source can be reached using the zip:// pseudo-protocol. The syntax is
-  * zip://myFile.xml@myZip.zip (zip://[file]@[archive])
-  * 
-  * @author <a href="http://apache.org/~reinhard">Reinhard Poetz</a>
-  * @version CVS $Id$
-  * @since 2.1.4
-  */ 
+/**
+ * Implementation of a {@link Source} that gets its content from
+ * a ZIP archive.
+ *
+ * <p>
+ * A ZIP source can be obtained using the <code>zip:</code> pseudo-protocol.
+ * The syntax for protocol is
+ * <pre>
+ *   zip:[archive-url]!/[file-path]
+ * </pre>
+ *
+ * Where, <code>archive-url</code> can be any supported Cocoon URL, and
+ * <code>file-path</code> is the path to the file within archive.
+ *
+ * @author <a href="http://apache.org/~reinhard">Reinhard Poetz</a>
+ * @version CVS $Id$
+ * @since 2.1.8
+ */
 public class ZipSourceFactory extends AbstractLogEnabled
-    implements SourceFactory, ThreadSafe, Serviceable {
+                              implements SourceFactory, ThreadSafe, Serviceable {
+
+    private ServiceManager manager;
+
+
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+    }
 
-    protected ServiceManager manager;
-    public final static String ZIP_SOURCE_SCHEME = "zip:";
 
     public Source getSource(String location, Map parameters)
-        throws IOException, MalformedURLException {
-        
-        if ( this.getLogger().isDebugEnabled() ) {
-            this.getLogger().debug("Processing " + location);
-        }
-        
-        // syntax checks
-        int separatorPos = location.indexOf('@');
-        if (separatorPos == -1) {
-            throw new MalformedURLException("@ required in URI: " + location);
-        }
-        int protocolEnd = location.indexOf("://");
+    throws IOException, MalformedURLException {
+        // Checks URL syntax
+        int protocolEnd = location.indexOf(":");
         if (protocolEnd == -1) {
-            throw new MalformedURLException("URI does not contain '://' : " + location);
+            throw new MalformedURLException("Protocol ':' separator is missing in URL: " + location);
         }
 
-        // get the source of the archive and return the ZipSource passing
-        // a source retrieved from the SourceResolver
-        String documentName = location.substring(protocolEnd + 3, separatorPos);
+        int archiveEnd = location.lastIndexOf("!/");
+        if (archiveEnd == -1) {
+            throw new MalformedURLException("File path '!/' separator is missing in URL: " + location);
+        }
+
+        // Get protocol. Protocol is configurable via cocoon.xconf
+        final String protocol = location.substring(0, protocolEnd - 1);
+
+        // Get archive URL
+        final String archiveURL = location.substring(protocolEnd + 1, archiveEnd);
+
+        // Get file path
+        final String filePath = location.substring(archiveEnd + 2);
+
+        // Resolve archive source
         Source archive;
         SourceResolver resolver = null;
         try {
-            resolver = (SourceResolver)this.manager.lookup( SourceResolver.ROLE );
-            archive = resolver.resolveURI(location.substring(separatorPos + 1));            
+            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
+            archive = resolver.resolveURI(archiveURL);
         } catch (ServiceException se) {
             throw new SourceException("SourceResolver is not available.", se);
         } finally {
             this.manager.release(resolver);
         }
-        return new ZipSource(archive, documentName);
-    }
 
-
-    public void release(Source source) {
-        // not necessary here
+        return new ZipSource(protocol, archive, filePath);
     }
 
-    public void service(ServiceManager manager) throws ServiceException {
-        this.manager = manager;
+    public void release(Source source) {
+        SourceResolver resolver = null;
+        try {
+            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
+            ((ZipSource) source).dispose(resolver);
+        } catch (ServiceException e) {
+            // Ignored
+            getLogger().error("ServiceException while looking up SourceResolver in release()", e);
+        } finally {
+            this.manager.release(resolver);
+        }
     }
-
 }

Modified: cocoon/blocks/scratchpad/trunk/samples/sources/sitemap.xmap
URL: http://svn.apache.org/viewcvs/cocoon/blocks/scratchpad/trunk/samples/sources/sitemap.xmap?rev=293608&r1=293607&r2=293608&view=diff
==============================================================================
--- cocoon/blocks/scratchpad/trunk/samples/sources/sitemap.xmap (original)
+++ cocoon/blocks/scratchpad/trunk/samples/sources/sitemap.xmap Tue Oct  4 07:38:53 2005
@@ -26,14 +26,14 @@
   <map:pipelines>
     <map:pipeline>
       <map:match pattern="simple-zip.xml">
-        <map:generate src="zip://test.xml@test.zip"/>
+        <map:generate src="zip:test.zip!/test.xml"/>
         <map:serialize type="xml"/>
       </map:match>
       <map:match pattern="simple-swx.xml">
-        <map:generate src="zip://content.xml@test.sxw"/>
+        <map:generate src="zip:test.sxw!/content.xml"/>
         <map:serialize type="xml"/>
-      </map:match>      
+      </map:match>
     </map:pipeline>
   </map:pipelines>
-  
+
 </map:sitemap>