fix 51671 - HWPFDocument.write based on NPOIFSFileSystem throws a NullPointerException

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1158754 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sergey Vladimirov 2011-08-17 14:53:28 +00:00
parent 7efd316c75
commit 8ea6b350e8
5 changed files with 124 additions and 62 deletions

View File

@ -34,6 +34,7 @@
<changes> <changes>
<release version="3.8-beta4" date="2011-??-??"> <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="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="fix">51535 - correct signed vs unsigned short reading in NDocumentInputStream</action>
<action dev="poi-developers" type="add">51634 - support SXSSF streaming from templates</action> <action dev="poi-developers" type="add">51634 - support SXSSF streaming from templates</action>

View 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.Entry;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.Internal;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -262,7 +263,8 @@ public abstract class POIDocument {
/** /**
* Copies an Entry into a target POIFS directory, recursively * 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 { throws IOException {
//System.err.println("copyNodeRecursively called with "+entry.getName()+ //System.err.println("copyNodeRecursively called with "+entry.getName()+
// ","+target.getName()); // ","+target.getName());

View File

@ -22,6 +22,7 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Iterator;
import org.apache.poi.hpsf.DocumentSummaryInformation; import org.apache.poi.hpsf.DocumentSummaryInformation;
import org.apache.poi.hpsf.SummaryInformation; 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.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentEntry; 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.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.Internal; 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_BIN_TABLES = "org.apache.poi.hwpf.preserveBinTables";
private static final String PROPERTY_PRESERVE_TEXT_TABLE = "org.apache.poi.hwpf.preserveTextTable"; 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 */ /** And for making sense of CP lengths in the FIB */
@Deprecated @Deprecated
protected CPSplitCalculator _cpSplit; protected CPSplitCalculator _cpSplit;
@ -181,7 +187,7 @@ public final class HWPFDocument extends HWPFDocumentCore
*/ */
public HWPFDocument(POIFSFileSystem pfilesystem) throws IOException 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 // Load the main stream and FIB
// Also handles HPSF bits // Also handles HPSF bits
super(directory); super(directory);
// Do the CP Split // Do the CP Split
_cpSplit = new CPSplitCalculator(_fib); _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. // use the fib to determine the name of the table stream.
String name = "0Table"; String name = STREAM_TABLE_0;
if (_fib.isFWhichTblStm()) if (_fib.isFWhichTblStm())
{ {
name = "1Table"; name = STREAM_TABLE_1;
} }
// Grab the table stream. // Grab the table stream.
DocumentEntry tableProps; DocumentEntry tableProps;
try { try {
tableProps = tableProps =
(DocumentEntry)directory.getEntry(name); (DocumentEntry)directory.getEntry(name);
} catch(FileNotFoundException fnfe) { } catch(FileNotFoundException fnfe) {
throw new IllegalStateException("Table Stream '" + name + "' wasn't found - Either the document is corrupt, or is Word95 (or earlier)"); throw new IllegalStateException("Table Stream '" + name + "' wasn't found - Either the document is corrupt, or is Word95 (or earlier)");
} }
// read in the table stream. // read in the table stream.
_tableStream = new byte[tableProps.getSize()]; _tableStream = new byte[tableProps.getSize()];
@ -249,9 +255,9 @@ public final class HWPFDocument extends HWPFDocumentCore
try try
{ {
DocumentEntry dataProps = DocumentEntry dataProps =
(DocumentEntry)directory.getEntry("Data"); (DocumentEntry)directory.getEntry(STREAM_DATA);
_dataStream = new byte[dataProps.getSize()]; _dataStream = new byte[dataProps.getSize()];
directory.createDocumentInputStream("Data").read(_dataStream); directory.createDocumentInputStream(STREAM_DATA).read(_dataStream);
} }
catch(java.io.FileNotFoundException e) catch(java.io.FileNotFoundException e)
{ {
@ -396,7 +402,7 @@ public final class HWPFDocument extends HWPFDocumentCore
@Deprecated @Deprecated
public CPSplitCalculator getCPSplitCalculator() public CPSplitCalculator getCPSplitCalculator()
{ {
return _cpSplit; return _cpSplit;
} }
public DocumentProperties getDocProperties() public DocumentProperties getDocProperties()
@ -512,7 +518,7 @@ public final class HWPFDocument extends HWPFDocumentCore
* separators and footnote separators. * separators and footnote separators.
*/ */
public Range getHeaderStoryRange() { 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 * @return PicturesTable object, that is able to extract images from this document
*/ */
public PicturesTable getPicturesTable() { public PicturesTable getPicturesTable() {
return _pictures; return _pictures;
} }
@Internal @Internal
@ -636,8 +642,8 @@ public final class HWPFDocument extends HWPFDocumentCore
{ {
// initialize our streams for writing. // initialize our streams for writing.
HWPFFileSystem docSys = new HWPFFileSystem(); HWPFFileSystem docSys = new HWPFFileSystem();
HWPFOutputStream wordDocumentStream = docSys.getStream("WordDocument"); HWPFOutputStream wordDocumentStream = docSys.getStream(STREAM_WORD_DOCUMENT);
HWPFOutputStream tableStream = docSys.getStream("1Table"); HWPFOutputStream tableStream = docSys.getStream(STREAM_TABLE_1);
//HWPFOutputStream dataStream = docSys.getStream("Data"); //HWPFOutputStream dataStream = docSys.getStream("Data");
int tableOffset = 0; int tableOffset = 0;
@ -910,6 +916,9 @@ public final class HWPFDocument extends HWPFDocumentCore
mainBuf = tempBuf; mainBuf = tempBuf;
} }
// Table1 stream will be used
_fib.setFWhichTblStm( true );
// write out the FileInformationBlock. // write out the FileInformationBlock.
//_fib.serialize(mainBuf, 0); //_fib.serialize(mainBuf, 0);
_fib.writeTo(mainBuf, tableStream); _fib.writeTo(mainBuf, tableStream);
@ -934,52 +943,84 @@ public final class HWPFDocument extends HWPFDocumentCore
dataBuf = tempBuf; dataBuf = tempBuf;
} }
// // spit out the Word document. // create new document preserving order of entries
// POIFSFileSystem pfs = new POIFSFileSystem(); POIFSFileSystem pfs = new POIFSFileSystem();
// boolean docWritten = false;
// pfs.createDocument(new ByteArrayInputStream(mainBuf), "WordDocument"); boolean dataWritten = false;
// pfs.createDocument(new ByteArrayInputStream(tableBuf), "1Table"); boolean tableWritten = false;
// pfs.createDocument(new ByteArrayInputStream(dataBuf), "Data"); boolean propertiesWritten = false;
// writeProperties(pfs); 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() );
}
}
POIFSFileSystem pfs = directory.getFileSystem(); if ( !docWritten )
deleteEntrySafe( pfs, "WordDocument" ); pfs.createDocument( new ByteArrayInputStream( mainBuf ),
deleteEntrySafe( pfs, "0Table" ); STREAM_WORD_DOCUMENT );
deleteEntrySafe( pfs, "1Table" ); if ( !tableWritten )
deleteEntrySafe( pfs, "Data" ); pfs.createDocument( new ByteArrayInputStream( tableBuf ),
STREAM_TABLE_1 );
if ( !propertiesWritten )
writeProperties( pfs );
if ( !dataWritten )
pfs.createDocument( new ByteArrayInputStream( dataBuf ),
STREAM_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" );
pfs.writeFilesystem( out ); pfs.writeFilesystem( out );
this.directory = pfs.getRoot();
/* /*
* since we updated all references in FIB and etc, using new arrays to * since we updated all references in FIB and etc, using new arrays to
* access data * access data
*/ */
this.directory = pfs.getRoot();
this._tableStream = tableStream.toByteArray(); this._tableStream = tableStream.toByteArray();
this._dataStream = dataBuf; this._dataStream = dataBuf;
} }
private static void deleteEntrySafe( POIFSFileSystem pfs, final String name )
{
try
{
pfs.getRoot().getEntry( name ).delete();
}
catch ( FileNotFoundException exc )
{
// ok
}
}
@Internal @Internal
public byte[] getDataStream() public byte[] getDataStream()
{ {
@ -988,7 +1029,7 @@ public final class HWPFDocument extends HWPFDocumentCore
@Internal @Internal
public byte[] getTableStream() public byte[] getTableStream()
{ {
return _tableStream; return _tableStream;
} }
public int registerList(HWPFList list) public int registerList(HWPFList list)

View File

@ -22,12 +22,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.PushbackInputStream; 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.EncryptedDocumentException;
import org.apache.poi.POIDocument; import org.apache.poi.POIDocument;
import org.apache.poi.hwpf.model.CHPBinTable; 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.SectionTable;
import org.apache.poi.hwpf.model.StyleSheet; import org.apache.poi.hwpf.model.StyleSheet;
import org.apache.poi.hwpf.model.TextPieceTable; 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.hwpf.usermodel.Range;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentEntry; import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem;
@ -53,6 +50,9 @@ import org.apache.poi.util.Internal;
*/ */
public abstract class HWPFDocumentCore extends POIDocument 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 */ /** Holds OLE2 objects */
protected ObjectPoolImpl _objectPool; protected ObjectPoolImpl _objectPool;
@ -151,7 +151,7 @@ public abstract class HWPFDocumentCore extends POIDocument
directory.getEntry("WordDocument"); directory.getEntry("WordDocument");
_mainStream = new byte[documentProps.getSize()]; _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 // Create our FIB, and check for the doc being encrypted
_fib = new FileInformationBlock(_mainStream); _fib = new FileInformationBlock(_mainStream);
@ -164,11 +164,12 @@ public abstract class HWPFDocumentCore extends POIDocument
try try
{ {
objectPoolEntry = (DirectoryEntry) directory objectPoolEntry = (DirectoryEntry) directory
.getEntry( "ObjectPool" ); .getEntry( STREAM_OBJECT_POOL );
} }
catch ( FileNotFoundException exc ) catch ( FileNotFoundException exc )
{ {
objectPoolEntry = directory.createDirectory( "ObjectPool" ); objectPoolEntry = directory
.createDirectory( STREAM_OBJECT_POOL );
} }
_objectPool = new ObjectPoolImpl( objectPoolEntry ); _objectPool = new ObjectPoolImpl( objectPoolEntry );
} }

View File

@ -16,6 +16,7 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.hwpf.usermodel; package org.apache.poi.hwpf.usermodel;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
@ -24,6 +25,8 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
@ -630,4 +633,18 @@ public class TestBugs extends TestCase
assertEquals( Arrays.toString( oldData ), Arrays.toString( newData ) ); 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() );
}
} }