r1550 - in xwiki/trunk: core/src/main/java/com/xpn/xwiki/plugin/zipexplorer src/test/java/com/xpn/xwiki/plugin/zipexplorer

Vincent Massol vmassol at users.forge.objectweb.org
Tue Nov 14 16:44:03 CET 2006


Author: vmassol
Date: 2006-11-14 16:44:02 +0100 (Tue, 14 Nov 2006)
New Revision: 1550

Modified:
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPlugin.java
   xwiki/trunk/core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPluginAPI.java
   xwiki/trunk/src/test/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerTest.java
Log:
Refactoring for the ZipExplorerPlugin class and its tests:
* finished adding javadocs
* finished refactoring unit tests so that they are executed in isolation
* added usage of commons-io for copying stream in memory and added warning


Modified: xwiki/trunk/core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPlugin.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPlugin.java	2006-11-14 11:24:11 UTC (rev 1549)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPlugin.java	2006-11-14 15:44:02 UTC (rev 1550)
@@ -34,8 +34,6 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.ByteArrayOutputStream;
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipEntry;
 import java.util.List;
@@ -45,6 +43,8 @@
 import java.util.Vector;
 import java.util.HashMap;
 
+import org.apache.commons.io.IOUtils;
+
 public class ZipExplorerPlugin extends XWikiDefaultPlugin {
 
     /**
@@ -92,15 +92,9 @@
     }
 
     /**
-     * For ZIP URLs of the format <code>http://[...]/zipfile.zip/SomeDirectory/SomeFile.txt</code> return a new
-     * attachment containing the file pointed to inside the ZIP. If the original attachment does not point to a ZIP
-     * file or if it doesn't specify a location inside the ZIP then do nothing and return the original attachment.
-     *
-     * @return a new attachment pointing to the file pointed to by the URL inside the ZIP or the original attachment
-     *         if the requested URL doesn't specify a file inside a ZIP
-     * @param attachment the original attachment
-     * @param context the XWiki context object containing the requested URL
-     * @see com.xpn.xwiki.plugin.XWikiDefaultPlugin#downloadAttachment(com.xpn.xwiki.doc.XWikiAttachment, com.xpn.xwiki.XWikiContext)
+     * See {@link com.xpn.xwiki.plugin.zipexplorer.ZipExplorerPluginAPI#downloadAttachment(com.xpn.xwiki.doc.XWikiAttachment)}
+     * for documentation. In addition the context parameter represents the XWiki context object containing the
+     * requested URL.
      */
     public XWikiAttachment downloadAttachment(XWikiAttachment attachment, XWikiContext context) {
         String url = context.getRequest().getRequestURI();
@@ -138,7 +132,12 @@
 
                 if (entryName.equals(filename)) {
                     newAttachment.setFilename(entryName);
-                    byte[] data = readFromInputStream(zis);
+
+                    // Note: We're copying the content of the file in the ZIP in memory. This is potentially going to
+                    // cause an error if the file's size is greater than the maximum size of a byte[] array in Java
+                    // or if there's not enough memomry.
+                    byte[] data = IOUtils.toByteArray(zis);
+
                     newAttachment.setFilesize(data.length);
                     newAttachment.setContent(data);
                     break;
@@ -154,34 +153,16 @@
     }
 
     /**
-     * @return the content of an entry in the zip file
+     * See {@link com.xpn.xwiki.plugin.zipexplorer.ZipExplorerPluginAPI#getFileList(com.xpn.xwiki.api.Document, String)}
+     * for documentation. In addition the context parameter is not used for now.
      */
-    private byte[] readFromInputStream(InputStream is) throws IOException {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        byte[] data = new byte[4096];
-        int count;
-        while ((count = is.read(data, 0, 4096)) != -1) {
-            baos.write(data, 0, count);
-        }
-        return baos.toByteArray();
-    }
-
-    public List getFileList(Document doc, String attachmentName, XWikiContext context) {
+    public List getFileList(Document document, String attachmentName, XWikiContext context) {
         List zipList = null;
 
         if (attachmentName.endsWith(".zip")) {
 
-            Attachment attachment = null;
-            List attachList = doc.getAttachmentList();
-            Iterator itr = attachList.iterator();
+            Attachment attachment = document.getAttachment(attachmentName);
 
-            while (itr.hasNext()) {
-                attachment = (Attachment)itr.next();
-                if (attachment.getFilename().equals(attachmentName)) {
-                    break;
-                }
-            }
-
             zipList = new ArrayList();
             byte[] stream;
             try {
@@ -204,8 +185,12 @@
         return zipList;
     }
 
-    public Vector getFileTreeList(Document doc, String attachmentName, XWikiContext context) {
-        List flatList = getFileList(doc, attachmentName, context);
+    /**
+     * See {@link com.xpn.xwiki.plugin.zipexplorer.ZipExplorerPluginAPI#getFileTreeList(com.xpn.xwiki.api.Document, String)}
+     * for documentation. In addition the context parameter is not used for now.
+     */
+    public Vector getFileTreeList(Document document, String attachmentName, XWikiContext context) {
+        List flatList = getFileList(document, attachmentName, context);
         Map fileTree = new HashMap();
         Iterator it = flatList.iterator();
         Vector res = new Vector();
@@ -229,8 +214,11 @@
         return res;
     }
 
-    String getFileLink(Document doc, String attachmentName, String fileName, XWikiContext context) {
-        String link = doc.getAttachmentURL(attachmentName);
-        return link + "/" + fileName;
+    /**
+     * See {@link com.xpn.xwiki.plugin.zipexplorer.ZipExplorerPluginAPI#getFileLink(com.xpn.xwiki.api.Document, String, String)}
+     * for documentation. In addition the context parameter is not used for now.
+     */
+    String getFileLink(Document document, String attachmentName, String fileName, XWikiContext context) {
+        return document.getAttachmentURL(attachmentName) + "/" + fileName;
     }
 }

Modified: xwiki/trunk/core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPluginAPI.java
===================================================================
--- xwiki/trunk/core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPluginAPI.java	2006-11-14 11:24:11 UTC (rev 1549)
+++ xwiki/trunk/core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPluginAPI.java	2006-11-14 15:44:02 UTC (rev 1550)
@@ -29,29 +29,73 @@
 import java.util.List;
 import java.util.Vector;
 
-
 public class ZipExplorerPluginAPI extends Api {
 
-    ZipExplorerPlugin plugin;
+    private ZipExplorerPlugin plugin;
 
     public ZipExplorerPluginAPI(ZipExplorerPlugin plugin, XWikiContext context) {
         super(context);
         this.plugin = plugin;
     }
 
+    /**
+     * For ZIP URLs of the format <code>http://[...]/zipfile.zip/SomeDirectory/SomeFile.txt</code> return a new
+     * attachment containing the file pointed to inside the ZIP. If the original attachment does not point to a ZIP
+     * file or if it doesn't specify a location inside the ZIP then do nothing and return the original attachment.
+     *
+     * @return a new attachment pointing to the file pointed to by the URL inside the ZIP or the original attachment
+     *         if the requested URL doesn't specify a file inside a ZIP
+     * @param attachment the original attachment
+     * @see com.xpn.xwiki.plugin.XWikiDefaultPlugin#downloadAttachment(com.xpn.xwiki.doc.XWikiAttachment, com.xpn.xwiki.XWikiContext)
+     */
     public XWikiAttachment downloadAttachment(XWikiAttachment attachment) {
         return this.plugin.downloadAttachment(attachment, context);
     }
 
-    public List getFileList(Document doc, String attachmentName) {
-        return this.plugin.getFileList(doc, attachmentName, context);
+    /**
+     * @return the list of file entries in the ZIP file attached under the passed attachment name inside the passed
+     *         document
+     * @param document the document containing the ZIP file as an attachment
+     * @param attachmentName the name under which the ZIP file is attached in the document
+     */
+    public List getFileList(Document document, String attachmentName) {
+        return this.plugin.getFileList(document, attachmentName, context);
     }
 
-    public Vector getFileTreeList(Document doc, String attachmentName) {
-        return this.plugin.getFileTreeList(doc, attachmentName, context);
+    /**
+     * Finds the ZIP attachement with passed name from the passed document matching and parse the ZIP to generate
+     * a list of {@link com.xpn.xwiki.objects.classes.ListItem} elements representing a tree view of all directories
+     * and files in the ZIP. For example the following zip:
+     * </p>
+     * <code><pre>
+     * zipfile.zip:
+     *   Directory/File.txt
+     *   File2.txt
+     * </per></code>
+     * generates the following ListItem list:
+     * <code><pre>
+     *   { id = "Directory/", value = "Directory", parent = ""}
+     *   { id = "Directory/File.txt", value = "File.txt", parent = "Directory/"}
+     *   { id = "File2.txt", value = "File2.txt", parent = ""}
+     * </per></code>
+     *
+     * @return a tree view list of {@link com.xpn.xwiki.objects.classes.ListItem} elements representing the content of
+     *         the ZIP file
+     * @param document the document containing the ZIP file as an attachment
+     * @param attachmentName the name under which the ZIP file is attached in the document
+     */
+    public Vector getFileTreeList(Document document, String attachmentName) {
+        return this.plugin.getFileTreeList(document, attachmentName, context);
     }
 
-    public String getFileLink(Document doc, String attachmentName, String fileName) {
-        return this.plugin.getFileLink(doc, attachmentName, fileName, context);
+    /**
+     * @return the attachment URL of the passed attachement located in the passed document to which the passed filename
+     *         has been suffixed.
+     * @param document the document containing the ZIP file as an attachment
+     * @param attachmentName the name under which the ZIP file is attached in the document
+     * @param fileName the filename to concatenate at the end of the attachment URL
+     */
+    public String getFileLink(Document document, String attachmentName, String fileName) {
+        return this.plugin.getFileLink(document, attachmentName, fileName, context);
     }
 }

Modified: xwiki/trunk/src/test/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerTest.java
===================================================================
--- xwiki/trunk/src/test/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerTest.java	2006-11-14 11:24:11 UTC (rev 1549)
+++ xwiki/trunk/src/test/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerTest.java	2006-11-14 15:44:02 UTC (rev 1550)
@@ -21,121 +21,147 @@
  */
 package com.xpn.xwiki.plugin.zipexplorer;
 
-import com.xpn.xwiki.XWikiException;
 import com.xpn.xwiki.XWikiContext;
+import com.xpn.xwiki.objects.classes.ListItem;
 import com.xpn.xwiki.api.Document;
 import com.xpn.xwiki.doc.XWikiAttachment;
 import com.xpn.xwiki.doc.XWikiDocument;
-import com.xpn.xwiki.test.HibernateTestCase;
-import com.xpn.xwiki.web.XWikiServletURLFactory;
+import com.xpn.xwiki.web.XWikiRequest;
+import org.jmock.Mock;
 
-import java.io.ByteArrayOutputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.Date;
 import java.util.List;
+import java.util.Vector;
+import java.util.zip.ZipOutputStream;
 import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
+import java.io.ByteArrayOutputStream;
 
-public class ZipExplorerTest extends HibernateTestCase {
+public class ZipExplorerTest extends org.jmock.cglib.MockObjectTestCase {
 
-    String zipfilename = "test.zip";
-    String author = "XWiki.LudovicDubost";
-    String parent = "Main.WebHome";
-    String content = "Hello 1\n" + "<Hello> 2\n" + "Hello 3";
+    private ZipExplorerPlugin plugin;
 
-    String filename1 = "test.doc";
-    String filename2 = "test.txt";
+    protected void setUp() {
+        this.plugin = new ZipExplorerPlugin("zipexplorer", ZipExplorerPlugin.class.getName(), null);
+    }
 
-    XWikiAttachment attachment;
-    XWikiDocument doc;
-    Document maindoc;
+    public void testDownloadAttachmentWithInvalidZipURL() throws Exception {
+        XWikiAttachment originalAttachment = createAttachment("someFile.txt", "Some text".getBytes(),
+            (XWikiDocument) mock(XWikiDocument.class).proxy());
+        XWikiContext context = createXWikiContext("http://server/xwiki/bin/download/Main/Document/someFile.txt");
 
-    List myExpectedList;
+        XWikiAttachment newAttachment = this.plugin.downloadAttachment(originalAttachment, context);
 
-    protected void setUp() throws Exception {
-        super.setUp();
-        getXWiki().getPluginManager().addPlugin("zipexplorer", "com.xpn.xwiki.plugin.zipexplorer.ZipExplorerPlugin", getXWikiContext());
-        getXWikiContext().setURLFactory(new XWikiServletURLFactory(new URL("http://www.xwiki.org/"), "xwiki/", "bin/"));
+        assertSame(originalAttachment, newAttachment);
     }
 
-    public void init() {
-        doc = new XWikiDocument("Main", "ZipExplorerTest");
-        doc.setContent(content);
-        doc.setAuthor(author);
-        doc.setParent(parent);
+    public void testDownloadAttachment() throws Exception {
+        String zipFileContent = "File.txt content";
+        XWikiAttachment originalAttachment = createAttachment("zipfile.zip", createZipFile(zipFileContent),
+            (XWikiDocument) mock(XWikiDocument.class).proxy());
+            
+        XWikiContext context = createXWikiContext(
+            "http://server/xwiki/bin/download/Main/Document/zipfile.zip/Directory/File.txt");
 
-        myExpectedList = new ArrayList();
-        myExpectedList.add(filename1);
-        myExpectedList.add(filename2);
+        XWikiAttachment newAttachment = this.plugin.downloadAttachment(originalAttachment, context);
 
-        try {
+        assertEquals("Directory/File.txt", newAttachment.getFilename());
+        assertEquals(zipFileContent.length(), newAttachment.getFilesize());
+        assertEquals(zipFileContent, new String(newAttachment.getContent(context)));
+    }
 
-            attachment = new XWikiAttachment(doc, zipfilename);
+    public void testGetFileList() throws Exception {
+        XWikiDocument document = createXWikiDocumentWithZipFileAttachment();
 
-            String attachcontent1 = "Hi i'm here";
-            byte[] stream = attachcontent1.getBytes();
+        List entries = this.plugin.getFileList(new Document(document, null), "zipfile.zip", null);
 
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            ZipOutputStream zos = new ZipOutputStream(baos);
+        assertEquals(2, entries.size());
+        assertEquals("Directory/File.txt", (String) entries.get(0));
+        assertEquals("File2.txt", (String) entries.get(1));
+    }
 
-            /* Each is the entry to the zip file */
+    public void testGetFileTreeList() throws Exception {
+        XWikiDocument document = createXWikiDocumentWithZipFileAttachment();
 
-            ZipEntry zipe = new ZipEntry(filename1);
-            zos.putNextEntry(zipe);
-            zos.write(stream, 0, stream.length);
+        Vector entries = this.plugin.getFileTreeList(new Document(document, null), "zipfile.zip", null);
 
-            zipe = new ZipEntry(filename2);
-            zos.putNextEntry(zipe);
-            zos.write(stream, 0, stream.length);
+        assertEquals(3, entries.size());
 
-            zos.closeEntry();
+        assertEquals("Directory/", ((ListItem) entries.get(0)).getId());
+        assertEquals("Directory", ((ListItem) entries.get(0)).getValue());
+        assertEquals("", ((ListItem) entries.get(0)).getParent());
 
-            attachment.setContent(baos.toByteArray());
-            doc.saveAttachmentContent(attachment, context);
+        assertEquals("Directory/File.txt", ((ListItem) entries.get(1)).getId());
+        assertEquals("File.txt", ((ListItem) entries.get(1)).getValue());
+        assertEquals("Directory/", ((ListItem) entries.get(1)).getParent());
 
-            doc.getAttachmentList().add(attachment);
-            xwiki.saveDocument(doc, context);
-            maindoc = new Document(doc, context);
-
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
+        assertEquals("File2.txt", ((ListItem) entries.get(2)).getId());
+        assertEquals("File2.txt", ((ListItem) entries.get(2)).getValue());
+        assertEquals("", ((ListItem) entries.get(2)).getParent());
     }
 
-    public void testZipExplorerTest() throws XWikiException {
-        init();
-        ZipExplorerPluginAPI zpa = (ZipExplorerPluginAPI) xwiki.getPluginApi("zipexplorer", context);
-        compareList(myExpectedList, zpa.getFileList(maindoc, attachment.getFilename()));
-        assertEquals("/xwiki/bin/download/Main/ZipExplorerTest/" + filename1,zpa.getFileLink(maindoc, attachment.getFilename(), filename1));
+    public void testGetFileLink() throws Exception {
+        Mock mockDocument = mock(XWikiDocument.class);
+        mockDocument.expects(once()).method("getAttachmentURL").will(
+            returnValue("http://server/xwiki/bin/download/Main/Document/zipfile.zip"));
+        Document document = new Document((XWikiDocument) mockDocument.proxy(), null);
+
+        String link = this.plugin.getFileLink(document, "zipfile.zip", "filename", null);
+
+        assertEquals("http://server/xwiki/bin/download/Main/Document/zipfile.zip/filename", link);
     }
 
-    public void testGetFileNameFromZipURL()
+    public void testGetFileLocationFromZipURL()
     {
-        ZipExplorerPlugin plugin = new ZipExplorerPlugin("zipexplorer",
-            ZipExplorerPlugin.class.getName(), new XWikiContext());
-        String fileName = plugin.getFileLocationFromZipURL(
-            "http://server/xwiki/bin/download/Main/Document/zipfile.zip/Directory/File.txt",
-            "download");
+        String fileName = this.plugin.getFileLocationFromZipURL(
+            "http://server/xwiki/bin/download/Main/Document/zipfile.zip/Directory/File.txt", "download");
         assertEquals("Directory/File.txt", fileName);
     }
 
-    public void testGetFileNameFromZipURLWhenInvalidURL()
+    public void testGetFileLocationFromZipURLWhenInvalidURL()
     {
-        ZipExplorerPlugin plugin = new ZipExplorerPlugin("zipexplorer",
-            ZipExplorerPlugin.class.getName(), new XWikiContext());
-        String fileName = plugin.getFileLocationFromZipURL(
-            "http://server/xwiki/bin/download/Main/Document/zipfile.zip",
-            "download");
+        String fileName = this.plugin.getFileLocationFromZipURL(
+            "http://server/xwiki/bin/download/Main/Document/zipfile.zip", "download");
         assertEquals("", fileName);
     }
 
-    private void compareList(List myExpectedList, List myResult){
-        assertEquals(myExpectedList.size(), myResult.size());
-        Iterator it = myResult.iterator();
-        while(it.hasNext()){
-            Object value = it.next();
-            assertTrue(myExpectedList.contains(value));
-        }
+    private XWikiDocument createXWikiDocumentWithZipFileAttachment() throws Exception {
+        Mock mockDocument = mock(XWikiDocument.class);
+        XWikiDocument document = (XWikiDocument) mockDocument.proxy();
+        XWikiAttachment attachment = createAttachment("zipfile.zip", createZipFile("Some content"), document);
+        mockDocument.stubs().method("clone").will(returnValue(mockDocument.proxy()));
+        mockDocument.stubs().method("getAttachment").will(returnValue(attachment));
+        return document;         
     }
+
+    private XWikiContext createXWikiContext(String url) {
+        Mock mockRequest = mock(XWikiRequest.class);
+        mockRequest.expects(once()).method("getRequestURI").will(returnValue(url));
+        XWikiContext context = new XWikiContext();
+        context.setRequest((XWikiRequest) mockRequest.proxy());
+        context.setAction("download");
+        return context;
+    }
+
+    private XWikiAttachment createAttachment(String filename, byte[] content, XWikiDocument document) throws Exception {
+        Mock mockAttachment = mock(XWikiAttachment.class);
+        mockAttachment.stubs().method("getFilename").will(returnValue(filename));
+        mockAttachment.stubs().method("getDoc").will(returnValue(document));
+        mockAttachment.stubs().method("getAuthor").will(returnValue("Vincent"));
+        mockAttachment.stubs().method("getDate").will(returnValue(new Date()));
+        mockAttachment.stubs().method("getContent").will(returnValue(content));
+        return (XWikiAttachment) mockAttachment.proxy();
+    }
+
+    private byte[] createZipFile(String content) throws Exception {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ZipOutputStream zos = new ZipOutputStream(baos);
+        ZipEntry zipe = new ZipEntry("Directory/File.txt");
+        zos.putNextEntry(zipe);
+        zos.write(content.getBytes());
+        ZipEntry zipe2 = new ZipEntry("File2.txt");
+        zos.putNextEntry(zipe2);
+        zos.write(content.getBytes());
+        zos.closeEntry();
+        return baos.toByteArray();
+    }
 }





More information about the Xwiki-notifications mailing list