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>
<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>

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.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());

View 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);
// 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() );
}
}
POIFSFileSystem pfs = directory.getFileSystem();
deleteEntrySafe( pfs, "WordDocument" );
deleteEntrySafe( pfs, "0Table" );
deleteEntrySafe( pfs, "1Table" );
deleteEntrySafe( pfs, "Data" );
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 );
// 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 );
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)

View 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 );
}

View 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() );
}
}