git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1753103 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_15_BETA3
@@ -22,6 +22,7 @@ import static org.apache.poi.hssf.model.InternalWorkbook.WORKBOOK_DIR_ENTRY_NAME | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.File; | |||
import java.io.FileNotFoundException; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
@@ -33,8 +34,8 @@ import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.HashSet; | |||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
@@ -77,8 +78,10 @@ import org.apache.poi.hssf.util.CellReference; | |||
import org.apache.poi.poifs.crypt.Decryptor; | |||
import org.apache.poi.poifs.filesystem.DirectoryEntry; | |||
import org.apache.poi.poifs.filesystem.DirectoryNode; | |||
import org.apache.poi.poifs.filesystem.DocumentNode; | |||
import org.apache.poi.poifs.filesystem.EntryUtils; | |||
import org.apache.poi.poifs.filesystem.FilteringDirectoryNode; | |||
import org.apache.poi.poifs.filesystem.NPOIFSDocument; | |||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; | |||
import org.apache.poi.poifs.filesystem.Ole10Native; | |||
import org.apache.poi.poifs.filesystem.POIFSFileSystem; | |||
@@ -1288,6 +1291,38 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss | |||
super.close(); | |||
} | |||
//@Override // TODO Not yet on POIDocument | |||
/** | |||
* Write out this workbook 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 | |||
* Workbook 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)} to write to a brand new stream. | |||
*/ | |||
public void write() throws IOException { | |||
// TODO Push much of this logic down to POIDocument, as will be common for most formats | |||
if (directory == null) { | |||
throw new IllegalStateException("Newly created Workbook, cannot save in-place"); | |||
} | |||
if (directory.getParent() != null) { | |||
throw new IllegalStateException("This is not the root document, cannot save in-place"); | |||
} | |||
if (directory.getFileSystem() == null || | |||
!directory.getFileSystem().isInPlaceWriteable()) { | |||
throw new IllegalStateException("Opened read-only or via an InputStream, a Writeable File"); | |||
} | |||
// Update the Workbook stream in the file | |||
DocumentNode workbookNode = (DocumentNode)directory.getEntry( | |||
getWorkbookDirEntryName(directory)); | |||
NPOIFSDocument workbookDoc = new NPOIFSDocument(workbookNode); | |||
workbookDoc.replaceContents(new ByteArrayInputStream(getBytes())); | |||
// Sync with the File on disk | |||
directory.getFileSystem().writeFilesystem(); | |||
} | |||
/** | |||
* Method write - write out this workbook to an {@link OutputStream}. Constructs | |||
* a new POI POIFSFileSystem, passes in the workbook binary representation and |
@@ -725,6 +725,21 @@ public class NPOIFSFileSystem extends BlockStore | |||
return getRoot().createDirectory(name); | |||
} | |||
/** | |||
* Does the filesystem support an in-place write via | |||
* {@link #writeFilesystem()} ? If false, only writing out to | |||
* a brand new file via {@link #writeFilesystem(OutputStream)} | |||
* is supported. | |||
*/ | |||
public boolean isInPlaceWriteable() { | |||
if(_data instanceof FileBackedDataSource) { | |||
if ( ((FileBackedDataSource)_data).isWriteable() ) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
/** | |||
* Write the filesystem out to the open file. Will thrown an | |||
* {@link IllegalArgumentException} if opened from an |
@@ -54,6 +54,7 @@ import org.apache.poi.hssf.record.WindowOneRecord; | |||
import org.apache.poi.poifs.filesystem.DirectoryEntry; | |||
import org.apache.poi.poifs.filesystem.DirectoryNode; | |||
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.ss.formula.ptg.Area3DPtg; | |||
import org.apache.poi.ss.usermodel.BaseTestWorkbook; | |||
@@ -66,6 +67,7 @@ import org.apache.poi.ss.usermodel.Sheet; | |||
import org.apache.poi.ss.usermodel.SheetConditionalFormatting; | |||
import org.apache.poi.ss.usermodel.Workbook; | |||
import org.apache.poi.ss.util.CellRangeAddress; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.TempFile; | |||
@@ -1210,4 +1212,69 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook { | |||
throw new Exception("Moving a sheet to the end should not throw an exception, but threw ", e); | |||
} | |||
} | |||
@Test | |||
public void invalidInPlaceWrite() throws Exception { | |||
HSSFWorkbook wb; | |||
// Can't work for new files | |||
wb = new HSSFWorkbook(); | |||
try { | |||
wb.write(); | |||
fail("Shouldn't work for new files"); | |||
} catch (IllegalStateException e) {} | |||
// Can't work for InputStream opened files | |||
wb = new HSSFWorkbook( | |||
POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SampleSS.xls")); | |||
try { | |||
wb.write(); | |||
fail("Shouldn't work for InputStream"); | |||
} catch (IllegalStateException e) {} | |||
// Can't work for OPOIFS | |||
OPOIFSFileSystem ofs = new OPOIFSFileSystem( | |||
POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SampleSS.xls")); | |||
wb = new HSSFWorkbook(ofs.getRoot(), true); | |||
try { | |||
wb.write(); | |||
fail("Shouldn't work for OPOIFSFileSystem"); | |||
} catch (IllegalStateException e) {} | |||
// Can't work for Read-Only files | |||
NPOIFSFileSystem fs = new NPOIFSFileSystem( | |||
POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xls"), true); | |||
wb = new HSSFWorkbook(fs); | |||
try { | |||
wb.write(); | |||
fail("Shouldn't work for Read Only"); | |||
} catch (IllegalStateException e) {} | |||
} | |||
@Test | |||
public void inPlaceWrite() throws Exception { | |||
// Setup as a copy of a known-good file | |||
final File file = TempFile.createTempFile("TestHSSFWorkbook", ".xls"); | |||
IOUtils.copy( | |||
POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SampleSS.xls"), | |||
new FileOutputStream(file) | |||
); | |||
// Open from the temp file in read-write mode | |||
HSSFWorkbook wb = new HSSFWorkbook(new NPOIFSFileSystem(file, false)); | |||
assertEquals(3, wb.getNumberOfSheets()); | |||
// Change | |||
wb.removeSheetAt(2); | |||
wb.removeSheetAt(1); | |||
wb.getSheetAt(0).getRow(0).getCell(0).setCellValue("Changed!"); | |||
// Save in-place, close, re-open and check | |||
wb.write(); | |||
wb.close(); | |||
wb = new HSSFWorkbook(new NPOIFSFileSystem(file)); | |||
assertEquals(1, wb.getNumberOfSheets()); | |||
assertEquals("Changed!", wb.getSheetAt(0).getRow(0).getCell(0).toString()); | |||
} | |||
} |