diff --git a/src/examples/src/org/apache/poi/hpsf/examples/CopyCompare.java b/src/examples/src/org/apache/poi/hpsf/examples/CopyCompare.java index f4b5ba10d0..5d27c968de 100644 --- a/src/examples/src/org/apache/poi/hpsf/examples/CopyCompare.java +++ b/src/examples/src/org/apache/poi/hpsf/examples/CopyCompare.java @@ -47,6 +47,7 @@ import org.apache.poi.poifs.filesystem.DocumentInputStream; import org.apache.poi.poifs.filesystem.Entry; import org.apache.poi.poifs.filesystem.POIFSDocumentPath; import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.TempFile; /** @@ -66,7 +67,7 @@ import org.apache.poi.util.TempFile; * exactly identical. However, both POI file systems must contain the same * files, and most of these files must be bitwise identical. Property set * streams, however, are compared logically: they must have the same sections - * with the same attributs, and the sections must contain the same properties. + * with the same attributes, and the sections must contain the same properties. * Details like the ordering of the properties do not matter.

*/ public class CopyCompare @@ -124,6 +125,7 @@ public class CopyCompare final POIFSReader r = new POIFSReader(); final CopyFile cf = new CopyFile(copyFileName); r.registerListener(cf); + r.setNotifyEmptyDirectories(true); FileInputStream fis = new FileInputStream(originalFileName); r.read(fis); fis.close(); @@ -133,19 +135,23 @@ public class CopyCompare /* Read all documents from the original POI file system and compare them * with the equivalent document from the copy. */ - final POIFSFileSystem opfs = new POIFSFileSystem(new File(originalFileName)); - final POIFSFileSystem cpfs = new POIFSFileSystem(new File(copyFileName)); - - final DirectoryEntry oRoot = opfs.getRoot(); - final DirectoryEntry cRoot = cpfs.getRoot(); - final StringBuffer messages = new StringBuffer(); - if (equal(oRoot, cRoot, messages)) { - System.out.println("Equal"); - } else { + POIFSFileSystem opfs = null, cpfs = null; + try { + opfs = new POIFSFileSystem(new File(originalFileName)); + cpfs = new POIFSFileSystem(new File(copyFileName)); + + final DirectoryEntry oRoot = opfs.getRoot(); + final DirectoryEntry cRoot = cpfs.getRoot(); + final StringBuffer messages = new StringBuffer(); + if (equal(oRoot, cRoot, messages)) { + System.out.println("Equal"); + } else { System.out.println("Not equal: " + messages); + } + } finally { + IOUtils.closeQuietly(cpfs); + IOUtils.closeQuietly(opfs); } - cpfs.close(); - opfs.close(); } @@ -179,15 +185,12 @@ public class CopyCompare /* Iterate over d1 and compare each entry with its counterpart in d2. */ for (final Entry e1 : d1) { final String n1 = e1.getName(); - Entry e2 = null; - try { - e2 = d2.getEntry(n1); - } catch (FileNotFoundException ex) { - msg.append("Document \"" + e1 + "\" exists, document \"" + - e2 + "\" does not.\n"); + if (!d2.hasEntry(n1)) { + msg.append("Document \"" + n1 + "\" exists only in the source.\n"); equal = false; break; } + Entry e2 = d2.getEntry(n1); if (e1.isDirectoryEntry() && e2.isDirectoryEntry()) { equal = equal((DirectoryEntry) e1, (DirectoryEntry) e2, msg); @@ -320,7 +323,7 @@ public class CopyCompare try { /* Find out whether the current document is a property set * stream or not. */ - if (PropertySet.isPropertySetStream(stream)) { + if (stream != null && PropertySet.isPropertySetStream(stream)) { /* Yes, the current document is a property set stream. * Let's create a PropertySet instance from it. */ PropertySet ps = null; @@ -337,7 +340,7 @@ public class CopyCompare } else { /* No, the current document is not a property set stream. We * copy it unmodified to the destination POIFS. */ - copy(poiFs, event.getPath(), event.getName(), stream); + copy(poiFs, path, name, stream); } } catch (MarkUnsupportedException ex) { t = ex; @@ -399,6 +402,10 @@ public class CopyCompare final DocumentInputStream stream) throws IOException { final DirectoryEntry de = getPath(poiFs, path); + if (stream == null && name == null) { + // Empty directory + return; + } final ByteArrayOutputStream out = new ByteArrayOutputStream(); int c; while ((c = stream.read()) != -1) { diff --git a/src/integrationtest/org/apache/poi/stress/HPSFFileHandler.java b/src/integrationtest/org/apache/poi/stress/HPSFFileHandler.java index 1f3dc69056..77ad5ef061 100644 --- a/src/integrationtest/org/apache/poi/stress/HPSFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/HPSFFileHandler.java @@ -16,33 +16,113 @@ ==================================================================== */ package org.apache.poi.stress; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertEquals; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; +import java.io.IOException; import java.io.InputStream; +import java.io.PrintStream; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import org.apache.poi.hpsf.DocumentSummaryInformation; import org.apache.poi.hpsf.HPSFPropertiesOnlyDocument; +import org.apache.poi.hpsf.MarkUnsupportedException; +import org.apache.poi.hpsf.PropertySet; +import org.apache.poi.hpsf.SummaryInformation; +import org.apache.poi.hpsf.examples.CopyCompare; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.DocumentInputStream; import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.TempFile; +import org.junit.Assume; import org.junit.Test; public class HPSFFileHandler extends POIFSFileHandler { - @Override - public void handleFile(InputStream stream) throws Exception { - HPSFPropertiesOnlyDocument hpsf = new HPSFPropertiesOnlyDocument(new POIFSFileSystem(stream)); - assertNotNull(hpsf.getDocumentSummaryInformation()); - assertNotNull(hpsf.getSummaryInformation()); + private static File copyOutput = null; + + static final Set EXCLUDES_HANDLE_ADD = unmodifiableHashSet( + "spreadsheet/45290.xls", + "spreadsheet/46904.xls", + "spreadsheet/55982.xls", + "spreadsheet/testEXCEL_3.xls", + "spreadsheet/testEXCEL_4.xls", + "hpsf/Test_Humor-Generation.ppt" + ); + + static final Set EXCLUDES_HANDLE_FILE = unmodifiableHashSet( + "hpsf/Test_Humor-Generation.ppt" + ); + + + private static final Set unmodifiableHashSet(String... a) { + return Collections.unmodifiableSet(new HashSet(Arrays.asList(a))); + } + + + @Override + public void handleFile(InputStream stream, String path) throws Exception { + Assume.assumeFalse(EXCLUDES_HANDLE_FILE.contains(path)); + POIFSFileSystem poifs = new POIFSFileSystem(stream); + HPSFPropertiesOnlyDocument hpsf = new HPSFPropertiesOnlyDocument(poifs); + DocumentSummaryInformation dsi = hpsf.getDocumentSummaryInformation(); + SummaryInformation si = hpsf.getSummaryInformation(); + boolean hasDSI = hasPropertyStream(poifs, DocumentSummaryInformation.DEFAULT_STREAM_NAME); + boolean hasSI = hasPropertyStream(poifs, SummaryInformation.DEFAULT_STREAM_NAME); + + assertEquals(hasDSI, dsi != null); + assertEquals(hasSI, si != null); handlePOIDocument(hpsf); } + + private static boolean hasPropertyStream(POIFSFileSystem poifs, String streamName) throws IOException, MarkUnsupportedException { + DirectoryNode root = poifs.getRoot(); + if (!root.hasEntry(streamName)) { + return false; + } + DocumentInputStream dis = root.createDocumentInputStream(streamName); + try { + return PropertySet.isPropertySetStream(dis); + } finally { + dis.close();; + } + } + + @Override + public void handleAdditional(File file) throws Exception { + Assume.assumeFalse(EXCLUDES_HANDLE_ADD.contains(file.getParentFile().getName()+"/"+file.getName())); + if (copyOutput == null) { + copyOutput = TempFile.createTempFile("hpsfCopy", "out"); + copyOutput.deleteOnExit(); + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + PrintStream psNew = new PrintStream(bos); + PrintStream ps = System.out; + try { + System.setOut(psNew); + CopyCompare.main(new String[]{file.getAbsolutePath(), copyOutput.getAbsolutePath()}); + assertEquals("Equal\n", new String(bos.toByteArray(), Charset.forName("UTF-8"))); + } finally { + System.setOut(ps); + } + } + // a test-case to test this locally without executing the full TestAllFiles @Override @Test public void test() throws Exception { - InputStream stream = new FileInputStream("test-data/hpsf/Test0313rur.adm"); + String path = "test-data/hpsf/Test0313rur.adm"; + InputStream stream = new FileInputStream(path); try { - handleFile(stream); + handleFile(stream, path); } finally { stream.close(); } diff --git a/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java index 633feba62d..c236c4b83b 100644 --- a/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java +++ b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java @@ -51,6 +51,7 @@ public class POIFSReader { private final POIFSReaderRegistry registry; private boolean registryClosed; + private boolean notifyEmptyDirectories = false; /** * Create a POIFSReader @@ -180,6 +181,18 @@ public class POIFSReader : path, name); } + /** + * Activates the notification of empty directories.

+ * If this flag is activated, the {@link POIFSReaderListener listener} receives + * {@link POIFSReaderEvent POIFSReaderEvents} with nulled {@code name} and {@code stream} + * + * @param notifyEmptyDirectories + */ + public void setNotifyEmptyDirectories(boolean notifyEmptyDirectories) { + this.notifyEmptyDirectories = notifyEmptyDirectories; + } + + /** * read in files * @@ -216,27 +229,27 @@ public class POIFSReader final BlockList big_blocks, final Iterator properties, final POIFSDocumentPath path) - throws IOException - { + throws IOException { + if (!properties.hasNext() && notifyEmptyDirectories) { + Iterator listeners = registry.getListeners(path, "."); + while (listeners.hasNext()) { + POIFSReaderListener pl = listeners.next(); + POIFSReaderEvent pe = new POIFSReaderEvent(null, path, null); + pl.processPOIFSReaderEvent(pe); + } + return; + } + while (properties.hasNext()) { Property property = properties.next(); String name = property.getName(); - if (property.isDirectory()) - { - POIFSDocumentPath new_path = new POIFSDocumentPath(path, - new String[] - { - name - }); - - processProperties( - small_blocks, big_blocks, - (( DirectoryProperty ) property).getChildren(), new_path); - } - else - { + if (property.isDirectory()) { + POIFSDocumentPath new_path = new POIFSDocumentPath(path,new String[]{name}); + DirectoryProperty dp = (DirectoryProperty) property; + processProperties(small_blocks, big_blocks, dp.getChildren(), new_path); + } else { int startBlock = property.getStartBlock(); Iterator listeners = registry.getListeners(path, name);