Modified: poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java?rev=1756967&r1=1756966&r2=1756967&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java (original) +++ poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java Fri Aug 19 20:57:56 2016 @@ -22,32 +22,10 @@ import java.io.File; 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; -import org.apache.poi.hwpf.model.BookmarksTables; -import org.apache.poi.hwpf.model.CHPBinTable; -import org.apache.poi.hwpf.model.ComplexFileTable; -import org.apache.poi.hwpf.model.DocumentProperties; -import org.apache.poi.hwpf.model.EscherRecordHolder; -import org.apache.poi.hwpf.model.FSPADocumentPart; -import org.apache.poi.hwpf.model.FSPATable; -import org.apache.poi.hwpf.model.FieldsTables; -import org.apache.poi.hwpf.model.FontTable; -import org.apache.poi.hwpf.model.ListTables; -import org.apache.poi.hwpf.model.NoteType; -import org.apache.poi.hwpf.model.NotesTables; -import org.apache.poi.hwpf.model.PAPBinTable; -import org.apache.poi.hwpf.model.PicturesTable; -import org.apache.poi.hwpf.model.RevisionMarkAuthorTable; -import org.apache.poi.hwpf.model.SavedByTable; -import org.apache.poi.hwpf.model.SectionTable; -import org.apache.poi.hwpf.model.SinglentonTextPiece; -import org.apache.poi.hwpf.model.StyleSheet; -import org.apache.poi.hwpf.model.SubdocumentType; -import org.apache.poi.hwpf.model.TextPiece; -import org.apache.poi.hwpf.model.TextPieceTable; +import org.apache.poi.hwpf.model.*; import org.apache.poi.hwpf.model.io.HWPFFileSystem; import org.apache.poi.hwpf.model.io.HWPFOutputStream; import org.apache.poi.hwpf.usermodel.Bookmarks; @@ -572,12 +550,27 @@ public final class HWPFDocument extends } /** - * Warning - not currently implemented for HWPF! + * Write out the word file that is represented by this class, to the + * currently open {@link File}, via the writeable {@link POIFSFileSystem} + * it was opened as. + * + * <p>This will fail (with an {@link IllegalStateException} if the + * Document was opened read-only, opened from an {@link InputStream} + * instead of a File, or if this is not the root document. For those cases, + * you must use {@link #write(OutputStream)} or {@link #write(File)} to + * write to a brand new document. + * + * @since 3.15 */ @Override public void write() throws IOException { - // TODO Implement - throw new IllegalStateException("Coming soon!"); + validateInPlaceWritePossible(); + + // Update the Document+Properties streams in the file + write(directory.getFileSystem(), false); + + // Sync with the File on disk + directory.getFileSystem().writeFilesystem(); } /** @@ -912,23 +905,18 @@ public final class HWPFDocument extends dataBuf = tempBuf; } - // create new document preserving order of entries - // TODO Check "copyOtherEntries" and tweak behaviour based on that - // TODO That's needed for in-place write + // Create a new document preserving order of entries / Update existing boolean docWritten = false; boolean dataWritten = false; boolean objectPoolWritten = false; boolean tableWritten = false; boolean propertiesWritten = false; - for ( Iterator<Entry> iter = directory.getEntries(); iter.hasNext(); ) - { - Entry entry = iter.next(); + for (Entry entry : directory) { if ( entry.getName().equals( STREAM_WORD_DOCUMENT ) ) { if ( !docWritten ) { - pfs.createDocument( new ByteArrayInputStream( mainBuf ), - STREAM_WORD_DOCUMENT ); + write(pfs, mainBuf, STREAM_WORD_DOCUMENT); docWritten = true; } } @@ -936,7 +924,11 @@ public final class HWPFDocument extends { if ( !objectPoolWritten ) { - _objectPool.writeTo( pfs.getRoot() ); + if ( copyOtherEntries ) { + _objectPool.writeTo( pfs.getRoot() ); + } else { + // Object pool is already there, no need to change/copy + } objectPoolWritten = true; } } @@ -945,8 +937,7 @@ public final class HWPFDocument extends { if ( !tableWritten ) { - pfs.createDocument( new ByteArrayInputStream( tableBuf ), - STREAM_TABLE_1 ); + write(pfs, tableBuf, STREAM_TABLE_1); tableWritten = true; } } @@ -965,29 +956,25 @@ public final class HWPFDocument extends { if ( !dataWritten ) { - pfs.createDocument( new ByteArrayInputStream( dataBuf ), - STREAM_DATA ); + write(pfs, dataBuf, STREAM_DATA); dataWritten = true; } } - else + else if ( copyOtherEntries ) { EntryUtils.copyNodeRecursively( entry, pfs.getRoot() ); } } if ( !docWritten ) - pfs.createDocument( new ByteArrayInputStream( mainBuf ), - STREAM_WORD_DOCUMENT ); + write(pfs, mainBuf, STREAM_WORD_DOCUMENT); if ( !tableWritten ) - pfs.createDocument( new ByteArrayInputStream( tableBuf ), - STREAM_TABLE_1 ); + write(pfs, tableBuf, STREAM_TABLE_1); if ( !propertiesWritten ) writeProperties( pfs ); if ( !dataWritten ) - pfs.createDocument( new ByteArrayInputStream( dataBuf ), - STREAM_DATA ); - if ( !objectPoolWritten ) + write(pfs, dataBuf, STREAM_DATA); + if ( !objectPoolWritten && copyOtherEntries ) _objectPool.writeTo( pfs.getRoot() ); this.directory = pfs.getRoot(); @@ -1000,6 +987,9 @@ public final class HWPFDocument extends this._tableStream = tableStream.toByteArray(); this._dataStream = dataBuf; } + private static void write(NPOIFSFileSystem pfs, byte[] data, String name) throws IOException { + pfs.createOrUpdateDocument(new ByteArrayInputStream(data), name); + } @Internal public byte[] getDataStream()
Modified: poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hwpf/sprm/SectionSprmUncompressor.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hwpf/sprm/SectionSprmUncompressor.java?rev=1756967&r1=1756966&r2=1756967&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hwpf/sprm/SectionSprmUncompressor.java (original) +++ poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hwpf/sprm/SectionSprmUncompressor.java Fri Aug 19 20:57:56 2016 @@ -24,11 +24,12 @@ import org.apache.poi.util.Internal; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; + @Internal public final class SectionSprmUncompressor extends SprmUncompressor { private static final POILogger logger = POILogFactory.getLogger(SectionSprmUncompressor.class); - + public SectionSprmUncompressor() { } @@ -58,15 +59,14 @@ public final class SectionSprmUncompress */ static void unCompressSEPOperation (SectionProperties newSEP, SprmOperation sprm) { - final int operation = sprm.getOperation(); - final int operand = sprm.getOperand(); + int operation = sprm.getOperation(); switch (operation) { case 0: - newSEP.setCnsPgn ((byte) operand); + newSEP.setCnsPgn ((byte) sprm.getOperand()); break; case 0x1: - newSEP.setIHeadingPgn ((byte) operand); + newSEP.setIHeadingPgn ((byte) sprm.getOperand()); break; case 0x2: byte[] buf = new byte[sprm.size() - 3]; @@ -80,110 +80,110 @@ public final class SectionSprmUncompress //not quite sure break; case 0x5: - newSEP.setFEvenlySpaced (getFlag (operand)); + newSEP.setFEvenlySpaced (getFlag (sprm.getOperand())); break; case 0x6: - newSEP.setFUnlocked (getFlag (operand)); + newSEP.setFUnlocked (getFlag (sprm.getOperand())); break; case 0x7: - newSEP.setDmBinFirst ((short) operand); + newSEP.setDmBinFirst ((short) sprm.getOperand()); break; case 0x8: - newSEP.setDmBinOther ((short) operand); + newSEP.setDmBinOther ((short) sprm.getOperand()); break; case 0x9: - newSEP.setBkc ((byte) operand); + newSEP.setBkc ((byte) sprm.getOperand()); break; case 0xa: - newSEP.setFTitlePage (getFlag (operand)); + newSEP.setFTitlePage (getFlag (sprm.getOperand())); break; case 0xb: - newSEP.setCcolM1 ((short) operand); + newSEP.setCcolM1 ((short) sprm.getOperand()); break; case 0xc: - newSEP.setDxaColumns (operand); + newSEP.setDxaColumns (sprm.getOperand()); break; case 0xd: - newSEP.setFAutoPgn (getFlag (operand)); + newSEP.setFAutoPgn (getFlag (sprm.getOperand())); break; case 0xe: - newSEP.setNfcPgn ((byte) operand); + newSEP.setNfcPgn ((byte) sprm.getOperand()); break; case 0xf: - newSEP.setDyaPgn ((short) operand); + newSEP.setDyaPgn ((short) sprm.getOperand()); break; case 0x10: - newSEP.setDxaPgn ((short) operand); + newSEP.setDxaPgn ((short) sprm.getOperand()); break; case 0x11: - newSEP.setFPgnRestart (getFlag (operand)); + newSEP.setFPgnRestart (getFlag (sprm.getOperand())); break; case 0x12: - newSEP.setFEndNote (getFlag (operand)); + newSEP.setFEndNote (getFlag (sprm.getOperand())); break; case 0x13: - newSEP.setLnc ((byte) operand); + newSEP.setLnc ((byte) sprm.getOperand()); break; case 0x14: - newSEP.setGrpfIhdt ((byte) operand); + newSEP.setGrpfIhdt ((byte) sprm.getOperand()); break; case 0x15: - newSEP.setNLnnMod ((short) operand); + newSEP.setNLnnMod ((short) sprm.getOperand()); break; case 0x16: - newSEP.setDxaLnn (operand); + newSEP.setDxaLnn (sprm.getOperand()); break; case 0x17: - newSEP.setDyaHdrTop (operand); + newSEP.setDyaHdrTop (sprm.getOperand()); break; case 0x18: - newSEP.setDyaHdrBottom (operand); + newSEP.setDyaHdrBottom (sprm.getOperand()); break; case 0x19: - newSEP.setFLBetween (getFlag (operand)); + newSEP.setFLBetween (getFlag (sprm.getOperand())); break; case 0x1a: - newSEP.setVjc ((byte) operand); + newSEP.setVjc ((byte) sprm.getOperand()); break; case 0x1b: - newSEP.setLnnMin ((short) operand); + newSEP.setLnnMin ((short) sprm.getOperand()); break; case 0x1c: - newSEP.setPgnStart ((short) operand); + newSEP.setPgnStart ((short) sprm.getOperand()); break; case 0x1d: - newSEP.setDmOrientPage( operand != 0 ); + newSEP.setDmOrientPage( sprm.getOperand() != 0 ); break; case 0x1e: //nothing break; case 0x1f: - newSEP.setXaPage (operand); + newSEP.setXaPage (sprm.getOperand()); break; case 0x20: - newSEP.setYaPage (operand); + newSEP.setYaPage (sprm.getOperand()); break; case 0x21: - newSEP.setDxaLeft (operand); + newSEP.setDxaLeft (sprm.getOperand()); break; case 0x22: - newSEP.setDxaRight (operand); + newSEP.setDxaRight (sprm.getOperand()); break; case 0x23: - newSEP.setDyaTop (operand); + newSEP.setDyaTop (sprm.getOperand()); break; case 0x24: - newSEP.setDyaBottom (operand); + newSEP.setDyaBottom (sprm.getOperand()); break; case 0x25: - newSEP.setDzaGutter (operand); + newSEP.setDzaGutter (sprm.getOperand()); break; case 0x26: - newSEP.setDmPaperReq ((short) operand); + newSEP.setDmPaperReq ((short) sprm.getOperand()); break; case 0x27: - newSEP.setFPropMark (getFlag (operand)); + newSEP.setFPropMark (getFlag (sprm.getOperand())); break; case 0x28: break; @@ -204,40 +204,40 @@ public final class SectionSprmUncompress newSEP.setBrcRight(new BorderCode(sprm.getGrpprl(), sprm.getGrpprlOffset())); break; case 0x2f: - newSEP.setPgbProp (operand); + newSEP.setPgbProp (sprm.getOperand()); break; case 0x30: - newSEP.setDxtCharSpace (operand); + newSEP.setDxtCharSpace (sprm.getOperand()); break; case 0x31: - newSEP.setDyaLinePitch (operand); + newSEP.setDyaLinePitch (sprm.getOperand()); break; case 0x33: - newSEP.setWTextFlow ((short) operand); + newSEP.setWTextFlow ((short) sprm.getOperand()); break; case 0x3C: // [MS-DOC], v20140721, 2.6.4, sprmSRncFtn - newSEP.setRncFtn((short) operand); + newSEP.setRncFtn((short) sprm.getOperand()); break; case 0x3E: // [MS-DOC], v20140721, 2.6.4, sprmSRncEdn - newSEP.setRncEdn((short) operand); + newSEP.setRncEdn((short) sprm.getOperand()); break; case 0x3F: // [MS-DOC], v20140721, 2.6.4, sprmSNFtn - newSEP.setNFtn(operand); + newSEP.setNFtn((int) sprm.getOperand()); break; case 0x40: // [MS-DOC], v20140721, 2.6.4, sprmSNFtnRef - newSEP.setNfcFtnRef(operand); + newSEP.setNfcFtnRef((int) sprm.getOperand()); break; case 0x41: // [MS-DOC], v20140721, 2.6.4, sprmSNEdn - newSEP.setNEdn(operand); + newSEP.setNEdn((int) sprm.getOperand()); break; case 0x42: // [MS-DOC], v20140721, 2.6.4, sprmSNEdnRef - newSEP.setNfcEdnRef(operand); + newSEP.setNfcEdnRef((int) sprm.getOperand()); break; default: logger.log(POILogger.INFO, "Unsupported Sprm operation: " + operation + " (" + HexDump.byteToHex(operation) + ")"); Modified: poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hslf/extractor/TestExtractor.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hslf/extractor/TestExtractor.java?rev=1756967&r1=1756966&r2=1756967&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hslf/extractor/TestExtractor.java (original) +++ poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hslf/extractor/TestExtractor.java Fri Aug 19 20:57:56 2016 @@ -18,6 +18,7 @@ package org.apache.poi.hslf.extractor; import static org.apache.poi.POITestCase.assertContains; +import static org.apache.poi.POITestCase.assertContainsIgnoreCase; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -26,7 +27,6 @@ import static org.junit.Assert.assertTru import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.List; -import java.util.Locale; import org.apache.poi.POIDataSamples; import org.apache.poi.hslf.model.OLEShape; @@ -355,7 +355,7 @@ public final class TestExtractor { ppe = new PowerPointExtractor(hslf); text = ppe.getText(); - assertContains(text.toLowerCase(Locale.ROOT), "master"); + assertContainsIgnoreCase(text, "master"); assertContains(text, masterText); } Modified: poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestHWPFWrite.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestHWPFWrite.java?rev=1756967&r1=1756966&r2=1756967&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestHWPFWrite.java (original) +++ poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestHWPFWrite.java Fri Aug 19 20:57:56 2016 @@ -21,11 +21,16 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileOutputStream; +import org.apache.poi.POIDataSamples; import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.HWPFTestCase; import org.apache.poi.hwpf.HWPFTestDataSamples; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.TempFile; /** @@ -75,7 +80,65 @@ public final class TestHWPFWrite extends r = doc.getRange(); assertEquals("I am a test document\r", r.getParagraph(0).text()); doc.close(); - } + } - // TODO In-place write positive and negative checks + /** + * Writing to the file we opened from - note, uses a temp file to + * avoid changing our test files! + */ + @SuppressWarnings("resource") + public void testInPlaceWrite() throws Exception { + // Setup as a copy of a known-good file + final File file = TempFile.createTempFile("TestDocument", ".doc"); + IOUtils.copy( + POIDataSamples.getDocumentInstance().openResourceAsStream("SampleDoc.doc"), + new FileOutputStream(file) + ); + + // Open from the temp file in read-write mode + HWPFDocument doc = new HWPFDocument(new NPOIFSFileSystem(file, false).getRoot()); + Range r = doc.getRange(); + assertEquals("I am a test document\r", r.getParagraph(0).text()); + + // Change + r.replaceText("X XX a test document\r", false); + + // Save in-place, close, re-open and check + doc.write(); + doc.close(); + + doc = new HWPFDocument(new NPOIFSFileSystem(file).getRoot()); + assertEquals("X XX a test document\r", r.getParagraph(0).text()); + } + + @SuppressWarnings("resource") + public void testInvalidInPlaceWrite() throws Exception { + HWPFDocument doc; + + // Can't work for InputStream opened files + doc = new HWPFDocument( + POIDataSamples.getDocumentInstance().openResourceAsStream("SampleDoc.doc")); + try { + doc.write(); + fail("Shouldn't work for InputStream"); + } catch (IllegalStateException e) {} + + // Can't work for OPOIFS + OPOIFSFileSystem ofs = new OPOIFSFileSystem( + POIDataSamples.getDocumentInstance().openResourceAsStream("SampleDoc.doc")); + doc = new HWPFDocument(ofs.getRoot()); + try { + doc.write(); + fail("Shouldn't work for OPOIFSFileSystem"); + } catch (IllegalStateException e) {} + + // Can't work for Read-Only files + NPOIFSFileSystem fs = new NPOIFSFileSystem( + POIDataSamples.getDocumentInstance().getFile("SampleDoc.doc"), true); + doc = new HWPFDocument(fs.getRoot()); + try { + doc.write(); + fail("Shouldn't work for Read Only"); + } catch (IllegalStateException e) {} + } } Modified: poi/branches/hssf_cryptoapi/src/testcases/org/apache/poi/POITestCase.java URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/testcases/org/apache/poi/POITestCase.java?rev=1756967&r1=1756966&r2=1756967&view=diff ============================================================================== --- poi/branches/hssf_cryptoapi/src/testcases/org/apache/poi/POITestCase.java (original) +++ poi/branches/hssf_cryptoapi/src/testcases/org/apache/poi/POITestCase.java Fri Aug 19 20:57:56 2016 @@ -32,13 +32,16 @@ import java.security.PrivilegedActionExc import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import org.apache.poi.util.SuppressForbidden; +import org.apache.poi.util.Internal; /** * Util class for POI JUnit TestCases, which provide additional features */ +@Internal public final class POITestCase { public static void assertContains(String haystack, String needle) { assertNotNull(haystack); @@ -47,6 +50,19 @@ public final class POITestCase { haystack.contains(needle) ); } + + public static void assertContainsIgnoreCase(String haystack, String needle, Locale locale) { + assertNotNull(haystack); + assertNotNull(needle); + String hay = haystack.toLowerCase(locale); + String n = needle.toLowerCase(locale); + assertTrue("Unable to find expected text '" + needle + "' in text:\n" + haystack, + hay.contains(n) + ); + } + public static void assertContainsIgnoreCase(String haystack, String needle) { + assertContainsIgnoreCase(haystack, needle, Locale.ROOT); + } public static void assertNotContained(String haystack, String needle) { assertNotNull(haystack); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
