]> source.dussan.org Git - poi.git/commitdiff
fix 51671 - HWPFDocument.write based on NPOIFSFileSystem throws a NullPointerException
authorSergey Vladimirov <sergey@apache.org>
Wed, 17 Aug 2011 14:53:28 +0000 (14:53 +0000)
committerSergey Vladimirov <sergey@apache.org>
Wed, 17 Aug 2011 14:53:28 +0000 (14:53 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1158754 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/POIDocument.java
src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java
src/scratchpad/src/org/apache/poi/hwpf/HWPFDocumentCore.java
src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBugs.java

index 9e157b9d00947d31778ed95adaed2d56c8b9b08a..99ab3a10e55109d6572fa79b451189daebd50241 100644 (file)
@@ -34,6 +34,7 @@
 
     <changes>
         <release version="3.8-beta4" date="2011-??-??">
+           <action dev="poi-developers" type="fix">51671 - HWPFDocument.write based on NPOIFSFileSystem throws a NullPointerException</action>
            <action dev="poi-developers" type="add">support for tables and hyperlinks in XSLF</action>
            <action dev="poi-developers" type="fix">51535 - correct signed vs unsigned short reading in NDocumentInputStream</action>
            <action dev="poi-developers" type="add">51634 - support SXSSF streaming from templates</action>
index f3a187f7f711cbdcb3b135521151547b44168883..fad5b47bc0453260f2f3f070d03f5d16c8faaea0 100644 (file)
@@ -36,6 +36,7 @@ import org.apache.poi.poifs.filesystem.DocumentInputStream;
 import org.apache.poi.poifs.filesystem.Entry;
 import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.util.Internal;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 
@@ -262,7 +263,8 @@ public abstract class POIDocument {
        /**
         * Copies an Entry into a target POIFS directory, recursively
         */
-       private void copyNodeRecursively(Entry entry, DirectoryEntry target)
+    @Internal
+       protected void copyNodeRecursively(Entry entry, DirectoryEntry target)
        throws IOException {
                //System.err.println("copyNodeRecursively called with "+entry.getName()+
                //                   ","+target.getName());
index b25ecc1ead8ef0d829f409b8666c9009b91d0aae..fc979f46d9a39e455fcd4898704fd4171c033909 100644 (file)
@@ -22,6 +22,7 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Iterator;
 
 import org.apache.poi.hpsf.DocumentSummaryInformation;
 import org.apache.poi.hpsf.SummaryInformation;
@@ -65,6 +66,7 @@ import org.apache.poi.hwpf.usermodel.Range;
 import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.poifs.filesystem.DirectoryNode;
 import org.apache.poi.poifs.filesystem.DocumentEntry;
+import org.apache.poi.poifs.filesystem.Entry;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.util.Internal;
 
@@ -81,6 +83,10 @@ public final class HWPFDocument extends HWPFDocumentCore
     private static final String PROPERTY_PRESERVE_BIN_TABLES = "org.apache.poi.hwpf.preserveBinTables";
     private static final String PROPERTY_PRESERVE_TEXT_TABLE = "org.apache.poi.hwpf.preserveTextTable";
 
+    private static final String STREAM_DATA = "Data";
+    private static final String STREAM_TABLE_0 = "0Table";
+    private static final String STREAM_TABLE_1 = "1Table";
+
   /** And for making sense of CP lengths in the FIB */
   @Deprecated
   protected CPSplitCalculator _cpSplit;
@@ -181,7 +187,7 @@ public final class HWPFDocument extends HWPFDocumentCore
    */
   public HWPFDocument(POIFSFileSystem pfilesystem) throws IOException
   {
-       this(pfilesystem.getRoot());
+    this(pfilesystem.getRoot());
   }
 
   /**
@@ -213,7 +219,7 @@ public final class HWPFDocument extends HWPFDocumentCore
   {
     // Load the main stream and FIB
     // Also handles HPSF bits
-       super(directory);
+    super(directory);
 
     // Do the CP Split
     _cpSplit = new CPSplitCalculator(_fib);
@@ -224,20 +230,20 @@ public final class HWPFDocument extends HWPFDocumentCore
     }
 
     // use the fib to determine the name of the table stream.
-    String name = "0Table";
+    String name = STREAM_TABLE_0;
     if (_fib.isFWhichTblStm())
     {
-      name = "1Table";
+      name = STREAM_TABLE_1;
     }
 
     // Grab the table stream.
     DocumentEntry tableProps;
-       try {
-               tableProps =
-                       (DocumentEntry)directory.getEntry(name);
-       } catch(FileNotFoundException fnfe) {
-               throw new IllegalStateException("Table Stream '" + name + "' wasn't found - Either the document is corrupt, or is Word95 (or earlier)");
-       }
+    try {
+        tableProps =
+            (DocumentEntry)directory.getEntry(name);
+    } catch(FileNotFoundException fnfe) {
+        throw new IllegalStateException("Table Stream '" + name + "' wasn't found - Either the document is corrupt, or is Word95 (or earlier)");
+    }
 
     // read in the table stream.
     _tableStream = new byte[tableProps.getSize()];
@@ -249,9 +255,9 @@ public final class HWPFDocument extends HWPFDocumentCore
     try
     {
       DocumentEntry dataProps =
-          (DocumentEntry)directory.getEntry("Data");
+          (DocumentEntry)directory.getEntry(STREAM_DATA);
       _dataStream = new byte[dataProps.getSize()];
-      directory.createDocumentInputStream("Data").read(_dataStream);
+      directory.createDocumentInputStream(STREAM_DATA).read(_dataStream);
     }
     catch(java.io.FileNotFoundException e)
     {
@@ -396,7 +402,7 @@ public final class HWPFDocument extends HWPFDocumentCore
   @Deprecated
   public CPSplitCalculator getCPSplitCalculator()
   {
-       return _cpSplit;
+    return _cpSplit;
   }
 
   public DocumentProperties getDocProperties()
@@ -512,7 +518,7 @@ public final class HWPFDocument extends HWPFDocumentCore
    *  separators and footnote separators.
    */
   public Range getHeaderStoryRange() {
-         return getRange( SubdocumentType.HEADER );
+      return getRange( SubdocumentType.HEADER );
   }
 
   /**
@@ -550,7 +556,7 @@ public final class HWPFDocument extends HWPFDocumentCore
    * @return PicturesTable object, that is able to extract images from this document
    */
   public PicturesTable getPicturesTable() {
-         return _pictures;
+      return _pictures;
   }
 
   @Internal
@@ -636,8 +642,8 @@ public final class HWPFDocument extends HWPFDocumentCore
   {
     // initialize our streams for writing.
     HWPFFileSystem docSys = new HWPFFileSystem();
-    HWPFOutputStream wordDocumentStream = docSys.getStream("WordDocument");
-    HWPFOutputStream tableStream = docSys.getStream("1Table");
+    HWPFOutputStream wordDocumentStream = docSys.getStream(STREAM_WORD_DOCUMENT);
+    HWPFOutputStream tableStream = docSys.getStream(STREAM_TABLE_1);
     //HWPFOutputStream dataStream = docSys.getStream("Data");
     int tableOffset = 0;
 
@@ -910,6 +916,9 @@ public final class HWPFDocument extends HWPFDocumentCore
       mainBuf = tempBuf;
     }
 
+        // Table1 stream will be used
+        _fib.setFWhichTblStm( true );
+
     // write out the FileInformationBlock.
     //_fib.serialize(mainBuf, 0);
     _fib.writeTo(mainBuf, tableStream);
@@ -934,52 +943,84 @@ public final class HWPFDocument extends HWPFDocumentCore
       dataBuf = tempBuf;
     }
 
-//    // spit out the Word document.
-//    POIFSFileSystem pfs = new POIFSFileSystem();
-//    
-//    pfs.createDocument(new ByteArrayInputStream(mainBuf), "WordDocument");
-//    pfs.createDocument(new ByteArrayInputStream(tableBuf), "1Table");
-//    pfs.createDocument(new ByteArrayInputStream(dataBuf), "Data");
-//    writeProperties(pfs);
-
-        POIFSFileSystem pfs = directory.getFileSystem();
-        deleteEntrySafe( pfs, "WordDocument" );
-        deleteEntrySafe( pfs, "0Table" );
-        deleteEntrySafe( pfs, "1Table" );
-        deleteEntrySafe( pfs, "Data" );
-
-        // read properties only if they were not read
-        getSummaryInformation();
-        // update properties in case user changed them
-        deleteEntrySafe( pfs, SummaryInformation.DEFAULT_STREAM_NAME );
-        deleteEntrySafe( pfs, DocumentSummaryInformation.DEFAULT_STREAM_NAME );
-        writeProperties( pfs );
-
-        pfs.createDocument( new ByteArrayInputStream( mainBuf ), "WordDocument" );
-        pfs.createDocument( new ByteArrayInputStream( tableBuf ), "1Table" );
-        pfs.createDocument( new ByteArrayInputStream( dataBuf ), "Data" );
+        // create new document preserving order of entries
+        POIFSFileSystem pfs = new POIFSFileSystem();
+        boolean docWritten = false;
+        boolean dataWritten = false;
+        boolean tableWritten = false;
+        boolean propertiesWritten = false;
+        for ( Iterator<Entry> iter = directory.getEntries(); iter.hasNext(); )
+        {
+            Entry entry = iter.next();
+            if ( entry.getName().equals( STREAM_WORD_DOCUMENT ) )
+            {
+                if ( !docWritten )
+                {
+                    pfs.createDocument( new ByteArrayInputStream( mainBuf ),
+                            STREAM_WORD_DOCUMENT );
+                    docWritten = true;
+                }
+            }
+            else if ( entry.getName().equals( STREAM_TABLE_0 )
+                    || entry.getName().equals( STREAM_TABLE_1 ) )
+            {
+                if ( !tableWritten )
+                {
+                    pfs.createDocument( new ByteArrayInputStream( tableBuf ),
+                            STREAM_TABLE_1 );
+                    tableWritten = true;
+                }
+            }
+            else if ( entry.getName().equals(
+                    SummaryInformation.DEFAULT_STREAM_NAME )
+                    || entry.getName().equals(
+                            DocumentSummaryInformation.DEFAULT_STREAM_NAME ) )
+            {
+                if ( !propertiesWritten )
+                {
+                    writeProperties( pfs );
+                    propertiesWritten = true;
+                }
+            }
+            else if ( entry.getName().equals( STREAM_DATA ) )
+            {
+                if ( !dataWritten )
+                {
+                    pfs.createDocument( new ByteArrayInputStream( dataBuf ),
+                            STREAM_DATA );
+                    dataWritten = true;
+                }
+            }
+            else
+            {
+                copyNodeRecursively( entry, pfs.getRoot() );
+            }
+        }
+
+        if ( !docWritten )
+            pfs.createDocument( new ByteArrayInputStream( mainBuf ),
+                    STREAM_WORD_DOCUMENT );
+        if ( !tableWritten )
+            pfs.createDocument( new ByteArrayInputStream( tableBuf ),
+                    STREAM_TABLE_1 );
+        if ( !propertiesWritten )
+            writeProperties( pfs );
+        if ( !dataWritten )
+            pfs.createDocument( new ByteArrayInputStream( dataBuf ),
+                    STREAM_DATA );
+
         pfs.writeFilesystem( out );
+        this.directory = pfs.getRoot();
 
         /*
          * since we updated all references in FIB and etc, using new arrays to
          * access data
          */
+        this.directory = pfs.getRoot();
         this._tableStream = tableStream.toByteArray();
         this._dataStream = dataBuf;
     }
 
-    private static void deleteEntrySafe( POIFSFileSystem pfs, final String name )
-    {
-        try
-        {
-            pfs.getRoot().getEntry( name ).delete();
-        }
-        catch ( FileNotFoundException exc )
-        {
-            // ok
-        }
-    }
-
   @Internal
   public byte[] getDataStream()
   {
@@ -988,7 +1029,7 @@ public final class HWPFDocument extends HWPFDocumentCore
   @Internal
   public byte[] getTableStream()
   {
-       return _tableStream;
+    return _tableStream;
   }
 
   public int registerList(HWPFList list)
index fc2bb15e68641e19fba7db48ba766118b33e1295..5301084a8ea42d028b666c80b5112d087adb0c9d 100644 (file)
@@ -22,12 +22,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.PushbackInputStream;
 
-import org.apache.poi.hwpf.usermodel.ObjectsPool;
-
-import org.apache.poi.poifs.filesystem.DirectoryEntry;
-
-import org.apache.poi.hwpf.usermodel.ObjectPoolImpl;
-
 import org.apache.poi.EncryptedDocumentException;
 import org.apache.poi.POIDocument;
 import org.apache.poi.hwpf.model.CHPBinTable;
@@ -38,7 +32,10 @@ import org.apache.poi.hwpf.model.PAPBinTable;
 import org.apache.poi.hwpf.model.SectionTable;
 import org.apache.poi.hwpf.model.StyleSheet;
 import org.apache.poi.hwpf.model.TextPieceTable;
+import org.apache.poi.hwpf.usermodel.ObjectPoolImpl;
+import org.apache.poi.hwpf.usermodel.ObjectsPool;
 import org.apache.poi.hwpf.usermodel.Range;
+import org.apache.poi.poifs.filesystem.DirectoryEntry;
 import org.apache.poi.poifs.filesystem.DirectoryNode;
 import org.apache.poi.poifs.filesystem.DocumentEntry;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
@@ -53,6 +50,9 @@ import org.apache.poi.util.Internal;
  */
 public abstract class HWPFDocumentCore extends POIDocument
 {
+    protected static final String STREAM_OBJECT_POOL = "ObjectPool";
+    protected static final String STREAM_WORD_DOCUMENT = "WordDocument";
+
   /** Holds OLE2 objects */
   protected ObjectPoolImpl _objectPool;
 
@@ -151,7 +151,7 @@ public abstract class HWPFDocumentCore extends POIDocument
        directory.getEntry("WordDocument");
     _mainStream = new byte[documentProps.getSize()];
 
-    directory.createDocumentInputStream("WordDocument").read(_mainStream);
+    directory.createDocumentInputStream(STREAM_WORD_DOCUMENT).read(_mainStream);
 
     // Create our FIB, and check for the doc being encrypted
     _fib = new FileInformationBlock(_mainStream);
@@ -164,11 +164,12 @@ public abstract class HWPFDocumentCore extends POIDocument
             try
             {
                 objectPoolEntry = (DirectoryEntry) directory
-                        .getEntry( "ObjectPool" );
+                        .getEntry( STREAM_OBJECT_POOL );
             }
             catch ( FileNotFoundException exc )
             {
-                objectPoolEntry = directory.createDirectory( "ObjectPool" );
+                objectPoolEntry = directory
+                        .createDirectory( STREAM_OBJECT_POOL );
             }
             _objectPool = new ObjectPoolImpl( objectPoolEntry );
         }
index a657a903ac75f967b8df8c211e7dc53eae72ce33..85d49387f1d8a3261500c3b21d46a4efc58a9c1a 100644 (file)
@@ -16,6 +16,7 @@
 ==================================================================== */
 package org.apache.poi.hwpf.usermodel;
 
+import java.io.ByteArrayOutputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -24,6 +25,8 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
+import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
+
 import junit.framework.TestCase;
 
 import org.apache.commons.codec.digest.DigestUtils;
@@ -630,4 +633,18 @@ public class TestBugs extends TestCase
 
         assertEquals( Arrays.toString( oldData ), Arrays.toString( newData ) );
     }
+
+    /**
+     * [RESOLVED FIXED] Bug 51671 - HWPFDocument.write based on NPOIFSFileSystem
+     * throws a NullPointerException
+     */
+    public void test51671() throws Exception
+    {
+        InputStream is = POIDataSamples.getDocumentInstance()
+                .openResourceAsStream( "empty.doc" );
+        NPOIFSFileSystem npoifsFileSystem = new NPOIFSFileSystem( is );
+        HWPFDocument hwpfDocument = new HWPFDocument(
+                npoifsFileSystem.getRoot() );
+        hwpfDocument.write( new ByteArrayOutputStream() );
+    }
 }