reuse existing POIFS of hwpf document to preserve all OLE streams

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1156727 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sergey Vladimirov 2011-08-11 18:49:35 +00:00
parent 3c5ee45591
commit 79ecde0c88
7 changed files with 128 additions and 65 deletions

View File

@ -23,8 +23,8 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.poi.hwpf.usermodel.ObjectPoolImpl; import org.apache.poi.hpsf.DocumentSummaryInformation;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hwpf.model.BookmarksTables; import org.apache.poi.hwpf.model.BookmarksTables;
import org.apache.poi.hwpf.model.CHPBinTable; import org.apache.poi.hwpf.model.CHPBinTable;
import org.apache.poi.hwpf.model.CPSplitCalculator; import org.apache.poi.hwpf.model.CPSplitCalculator;
@ -636,7 +636,7 @@ 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 mainStream = docSys.getStream("WordDocument"); HWPFOutputStream wordDocumentStream = docSys.getStream("WordDocument");
HWPFOutputStream tableStream = docSys.getStream("1Table"); HWPFOutputStream tableStream = docSys.getStream("1Table");
//HWPFOutputStream dataStream = docSys.getStream("Data"); //HWPFOutputStream dataStream = docSys.getStream("Data");
int tableOffset = 0; int tableOffset = 0;
@ -653,8 +653,8 @@ public final class HWPFDocument extends HWPFDocumentCore
// preserve space for the FileInformationBlock because we will be writing // preserve space for the FileInformationBlock because we will be writing
// it after we write everything else. // it after we write everything else.
byte[] placeHolder = new byte[fibSize]; byte[] placeHolder = new byte[fibSize];
mainStream.write(placeHolder); wordDocumentStream.write(placeHolder);
int mainOffset = mainStream.getOffset(); int mainOffset = wordDocumentStream.getOffset();
// write out the StyleSheet. // write out the StyleSheet.
_fib.setFcStshf(tableOffset); _fib.setFcStshf(tableOffset);
@ -677,10 +677,10 @@ public final class HWPFDocument extends HWPFDocumentCore
// write out the Complex table, includes text. // write out the Complex table, includes text.
_fib.setFcClx(tableOffset); _fib.setFcClx(tableOffset);
_cft.writeTo(docSys); _cft.writeTo(wordDocumentStream, tableStream);
_fib.setLcbClx(tableStream.getOffset() - tableOffset); _fib.setLcbClx(tableStream.getOffset() - tableOffset);
tableOffset = tableStream.getOffset(); tableOffset = tableStream.getOffset();
int fcMac = mainStream.getOffset(); int fcMac = wordDocumentStream.getOffset();
/* /*
* dop (document properties record) Written immediately after the end of * dop (document properties record) Written immediately after the end of
@ -733,7 +733,7 @@ public final class HWPFDocument extends HWPFDocumentCore
// write out the CHPBinTable. // write out the CHPBinTable.
_fib.setFcPlcfbteChpx(tableOffset); _fib.setFcPlcfbteChpx(tableOffset);
_cbt.writeTo(docSys, fcMin, _cft.getTextPieceTable()); _cbt.writeTo(wordDocumentStream, tableStream, fcMin, _cft.getTextPieceTable());
_fib.setLcbPlcfbteChpx(tableStream.getOffset() - tableOffset); _fib.setLcbPlcfbteChpx(tableStream.getOffset() - tableOffset);
tableOffset = tableStream.getOffset(); tableOffset = tableStream.getOffset();
@ -747,7 +747,7 @@ public final class HWPFDocument extends HWPFDocumentCore
// write out the PAPBinTable. // write out the PAPBinTable.
_fib.setFcPlcfbtePapx(tableOffset); _fib.setFcPlcfbtePapx(tableOffset);
_pbt.writeTo(docSys, _cft.getTextPieceTable()); _pbt.writeTo(wordDocumentStream, tableStream, _cft.getTextPieceTable());
_fib.setLcbPlcfbtePapx(tableStream.getOffset() - tableOffset); _fib.setLcbPlcfbtePapx(tableStream.getOffset() - tableOffset);
tableOffset = tableStream.getOffset(); tableOffset = tableStream.getOffset();
@ -804,7 +804,7 @@ public final class HWPFDocument extends HWPFDocumentCore
// write out the SectionTable. // write out the SectionTable.
_fib.setFcPlcfsed(tableOffset); _fib.setFcPlcfsed(tableOffset);
_st.writeTo(docSys, fcMin); _st.writeTo(wordDocumentStream, tableStream);
_fib.setLcbPlcfsed(tableStream.getOffset() - tableOffset); _fib.setLcbPlcfsed(tableStream.getOffset() - tableOffset);
tableOffset = tableStream.getOffset(); tableOffset = tableStream.getOffset();
@ -892,17 +892,17 @@ public final class HWPFDocument extends HWPFDocumentCore
// write out the FontTable. // write out the FontTable.
_fib.setFcSttbfffn(tableOffset); _fib.setFcSttbfffn(tableOffset);
_ft.writeTo(docSys); _ft.writeTo(tableStream);
_fib.setLcbSttbfffn(tableStream.getOffset() - tableOffset); _fib.setLcbSttbfffn(tableStream.getOffset() - tableOffset);
tableOffset = tableStream.getOffset(); tableOffset = tableStream.getOffset();
// set some variables in the FileInformationBlock. // set some variables in the FileInformationBlock.
_fib.setFcMin(fcMin); _fib.setFcMin(fcMin);
_fib.setFcMac(fcMac); _fib.setFcMac(fcMac);
_fib.setCbMac(mainStream.getOffset()); _fib.setCbMac(wordDocumentStream.getOffset());
// make sure that the table, doc and data streams use big blocks. // make sure that the table, doc and data streams use big blocks.
byte[] mainBuf = mainStream.toByteArray(); byte[] mainBuf = wordDocumentStream.toByteArray();
if (mainBuf.length < 4096) if (mainBuf.length < 4096)
{ {
byte[] tempBuf = new byte[4096]; byte[] tempBuf = new byte[4096];
@ -934,15 +934,31 @@ public final class HWPFDocument extends HWPFDocumentCore
dataBuf = tempBuf; 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);
// spit out the Word document. POIFSFileSystem pfs = directory.getFileSystem();
POIFSFileSystem pfs = new POIFSFileSystem(); deleteEntrySafe( pfs, "WordDocument" );
pfs.createDocument(new ByteArrayInputStream(mainBuf), "WordDocument"); deleteEntrySafe( pfs, "0Table" );
pfs.createDocument(new ByteArrayInputStream(tableBuf), "1Table"); deleteEntrySafe( pfs, "1Table" );
pfs.createDocument(new ByteArrayInputStream(dataBuf), "Data"); deleteEntrySafe( pfs, "Data" );
writeProperties(pfs);
pfs.writeFilesystem(out); // 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 );
/* /*
* 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
@ -952,6 +968,18 @@ public final class HWPFDocument extends HWPFDocumentCore
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()
{ {

View File

@ -451,12 +451,20 @@ public class CHPBinTable
return _textRuns; return _textRuns;
} }
public void writeTo(HWPFFileSystem sys, int fcMin, CharIndexTranslator translator) @Deprecated
throws IOException public void writeTo( HWPFFileSystem sys, int fcMin,
{ CharIndexTranslator translator ) throws IOException
{
HWPFOutputStream docStream = sys.getStream( "WordDocument" );
HWPFOutputStream tableStream = sys.getStream( "1Table" );
HWPFOutputStream docStream = sys.getStream("WordDocument"); writeTo( docStream, tableStream, fcMin, translator );
OutputStream tableStream = sys.getStream("1Table"); }
public void writeTo( HWPFOutputStream wordDocumentStream,
HWPFOutputStream tableStream, int fcMin,
CharIndexTranslator translator ) throws IOException
{
/* /*
* Page 35: * Page 35:
@ -469,16 +477,16 @@ public class CHPBinTable
PlexOfCps bte = new PlexOfCps( 4 ); PlexOfCps bte = new PlexOfCps( 4 );
// each FKP must start on a 512 byte page. // each FKP must start on a 512 byte page.
int docOffset = docStream.getOffset(); int docOffset = wordDocumentStream.getOffset();
int mod = docOffset % POIFSConstants.SMALLER_BIG_BLOCK_SIZE; int mod = docOffset % POIFSConstants.SMALLER_BIG_BLOCK_SIZE;
if (mod != 0) if (mod != 0)
{ {
byte[] padding = new byte[POIFSConstants.SMALLER_BIG_BLOCK_SIZE - mod]; byte[] padding = new byte[POIFSConstants.SMALLER_BIG_BLOCK_SIZE - mod];
docStream.write(padding); wordDocumentStream.write(padding);
} }
// get the page number for the first fkp // get the page number for the first fkp
docOffset = docStream.getOffset(); docOffset = wordDocumentStream.getOffset();
int pageNum = docOffset/POIFSConstants.SMALLER_BIG_BLOCK_SIZE; int pageNum = docOffset/POIFSConstants.SMALLER_BIG_BLOCK_SIZE;
// get the ending fc // get the ending fc
@ -499,7 +507,7 @@ public class CHPBinTable
cfkp.fill(overflow); cfkp.fill(overflow);
byte[] bufFkp = cfkp.toByteArray( translator ); byte[] bufFkp = cfkp.toByteArray( translator );
docStream.write(bufFkp); wordDocumentStream.write(bufFkp);
overflow = cfkp.getOverflow(); overflow = cfkp.getOverflow();
int end = endingFc; int end = endingFc;

View File

@ -80,20 +80,26 @@ public final class ComplexFileTable
return _grpprls; return _grpprls;
} }
public void writeTo(HWPFFileSystem sys) @Deprecated
throws IOException public void writeTo( HWPFFileSystem sys ) throws IOException
{ {
HWPFOutputStream docStream = sys.getStream("WordDocument"); HWPFOutputStream docStream = sys.getStream( "WordDocument" );
HWPFOutputStream tableStream = sys.getStream("1Table"); HWPFOutputStream tableStream = sys.getStream( "1Table" );
tableStream.write(TEXT_PIECE_TABLE_TYPE); writeTo( docStream, tableStream );
}
byte[] table = _tpt.writeTo(docStream); public void writeTo( HWPFOutputStream wordDocumentStream,
HWPFOutputStream tableStream ) throws IOException
{
tableStream.write( TEXT_PIECE_TABLE_TYPE );
byte[] numHolder = new byte[LittleEndian.INT_SIZE]; byte[] table = _tpt.writeTo( wordDocumentStream );
LittleEndian.putInt(numHolder, table.length);
tableStream.write(numHolder); byte[] numHolder = new byte[LittleEndian.INT_SIZE];
tableStream.write(table); LittleEndian.putInt( numHolder, table.length );
} tableStream.write( numHolder );
tableStream.write( table );
}
} }

View File

@ -115,11 +115,15 @@ public final class FontTable
this._stringCount = stringCount; this._stringCount = stringCount;
} }
public void writeTo(HWPFFileSystem sys) @Deprecated
throws IOException public void writeTo( HWPFFileSystem sys ) throws IOException
{ {
HWPFOutputStream tableStream = sys.getStream("1Table"); HWPFOutputStream tableStream = sys.getStream( "1Table" );
writeTo( tableStream );
}
public void writeTo( HWPFOutputStream tableStream ) throws IOException
{
byte[] buf = new byte[LittleEndian.SHORT_SIZE]; byte[] buf = new byte[LittleEndian.SHORT_SIZE];
LittleEndian.putShort(buf, _stringCount); LittleEndian.putShort(buf, _stringCount);
tableStream.write(buf); tableStream.write(buf);

View File

@ -397,26 +397,34 @@ public class PAPBinTable
return _paragraphs; return _paragraphs;
} }
public void writeTo( HWPFFileSystem sys, CharIndexTranslator translator ) throws IOException @Deprecated
public void writeTo( HWPFFileSystem sys, CharIndexTranslator translator )
throws IOException
{ {
HWPFOutputStream wordDocumentStream = sys.getStream( "WordDocument" );
HWPFOutputStream tableStream = sys.getStream( "1Table" );
HWPFOutputStream docStream = sys.getStream("WordDocument"); writeTo( wordDocumentStream, tableStream, translator );
OutputStream tableStream = sys.getStream("1Table"); }
HWPFOutputStream dataStream = sys.getStream("1Table");
public void writeTo( HWPFOutputStream wordDocumentStream,
HWPFOutputStream tableStream, CharIndexTranslator translator )
throws IOException
{
PlexOfCps binTable = new PlexOfCps(4); PlexOfCps binTable = new PlexOfCps(4);
// each FKP must start on a 512 byte page. // each FKP must start on a 512 byte page.
int docOffset = docStream.getOffset(); int docOffset = wordDocumentStream.getOffset();
int mod = docOffset % POIFSConstants.SMALLER_BIG_BLOCK_SIZE; int mod = docOffset % POIFSConstants.SMALLER_BIG_BLOCK_SIZE;
if (mod != 0) if (mod != 0)
{ {
byte[] padding = new byte[POIFSConstants.SMALLER_BIG_BLOCK_SIZE - mod]; byte[] padding = new byte[POIFSConstants.SMALLER_BIG_BLOCK_SIZE - mod];
docStream.write(padding); wordDocumentStream.write(padding);
} }
// get the page number for the first fkp // get the page number for the first fkp
docOffset = docStream.getOffset(); docOffset = wordDocumentStream.getOffset();
int pageNum = docOffset/POIFSConstants.SMALLER_BIG_BLOCK_SIZE; int pageNum = docOffset/POIFSConstants.SMALLER_BIG_BLOCK_SIZE;
// get the ending fc // get the ending fc
@ -436,8 +444,8 @@ public class PAPBinTable
PAPFormattedDiskPage pfkp = new PAPFormattedDiskPage(); PAPFormattedDiskPage pfkp = new PAPFormattedDiskPage();
pfkp.fill(overflow); pfkp.fill(overflow);
byte[] bufFkp = pfkp.toByteArray(dataStream, translator); byte[] bufFkp = pfkp.toByteArray(tableStream, translator);
docStream.write(bufFkp); wordDocumentStream.write(bufFkp);
overflow = pfkp.getOverflow(); overflow = pfkp.getOverflow();
int end = endingFc; int end = endingFc;

View File

@ -165,13 +165,20 @@ public class SectionTable
return _sections; return _sections;
} }
public void writeTo(HWPFFileSystem sys, int fcMin) @Deprecated
throws IOException public void writeTo( HWPFFileSystem sys, int fcMin ) throws IOException
{ {
HWPFOutputStream docStream = sys.getStream("WordDocument"); HWPFOutputStream docStream = sys.getStream( "WordDocument" );
HWPFOutputStream tableStream = sys.getStream("1Table"); HWPFOutputStream tableStream = sys.getStream( "1Table" );
int offset = docStream.getOffset(); writeTo( docStream, tableStream );
}
public void writeTo( HWPFOutputStream wordDocumentStream,
HWPFOutputStream tableStream ) throws IOException
{
int offset = wordDocumentStream.getOffset();
int len = _sections.size(); int len = _sections.size();
PlexOfCps plex = new PlexOfCps(SED_SIZE); PlexOfCps plex = new PlexOfCps(SED_SIZE);
@ -185,8 +192,8 @@ public class SectionTable
byte[] shortBuf = new byte[2]; byte[] shortBuf = new byte[2];
LittleEndian.putShort(shortBuf, (short)grpprl.length); LittleEndian.putShort(shortBuf, (short)grpprl.length);
docStream.write(shortBuf); wordDocumentStream.write(shortBuf);
docStream.write(grpprl); wordDocumentStream.write(grpprl);
// set the fc in the section descriptor // set the fc in the section descriptor
SectionDescriptor sed = sepx.getSectionDescriptor(); SectionDescriptor sed = sepx.getSectionDescriptor();
@ -212,7 +219,7 @@ public class SectionTable
plex.addProperty(property); plex.addProperty(property);
offset = docStream.getOffset(); offset = wordDocumentStream.getOffset();
} }
tableStream.write(plex.toByteArray()); tableStream.write(plex.toByteArray());
} }

View File

@ -17,6 +17,7 @@
package org.apache.poi.hwpf.usermodel; package org.apache.poi.hwpf.usermodel;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Arrays; import java.util.Arrays;
@ -551,7 +552,7 @@ public class TestBugs extends TestCase
* @throws IOException * @throws IOException
* @throws FileNotFoundException * @throws FileNotFoundException
*/ */
public void test51604p2() throws FileNotFoundException, IOException public void test51604p2() throws Exception
{ {
HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "Bug51604.doc" ); HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "Bug51604.doc" );
@ -583,13 +584,14 @@ public class TestBugs extends TestCase
totalLength += partLength; totalLength += partLength;
} }
assertEquals( doc.getText().length(), totalLength );
} }
/** /**
* [RESOLVED FIXED] Bug 51604 - replace text fails for doc ( poi 3.8 beta * [RESOLVED FIXED] Bug 51604 - replace text fails for doc ( poi 3.8 beta
* release from download site ) * release from download site )
*/ */
public void test51604p3() throws IOException public void test51604p3() throws Exception
{ {
HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "Bug51604.doc" ); HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "Bug51604.doc" );