]> source.dussan.org Git - poi.git/commitdiff
Improve handling and warnings when closing OPCPackage objects
authorNick Burch <nick@apache.org>
Wed, 4 Aug 2010 15:58:51 +0000 (15:58 +0000)
committerNick Burch <nick@apache.org>
Wed, 4 Aug 2010 15:58:51 +0000 (15:58 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@982311 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/status.xml
src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java
src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java
src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java

index d5e39d391866061ea8c214e47328dff4e1441f6d..040594cecf5d8586758909d7a599acd093ca8b05 100644 (file)
@@ -34,6 +34,7 @@
 
     <changes>
         <release version="3.7-beta2" date="2010-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">Improve handling and warnings when closing OPCPackage objects</action>
            <action dev="POI-DEVELOPERS" type="fix">49702 - Correct XSSFWorkbook.getNumCellStyles to check the right styles list</action>
            <action dev="POI-DEVELOPERS" type="add">49690 - Add WorkbookUtil, which provies a way of generating valid sheet names</action>
            <action dev="POI-DEVELOPERS" type="fix">49694 - Use DataFormatter when autosizing columns, to better match the real display width of formatted cells</action>
index fe2c3e279939d58e2c47b61712ff3d7ef95992d4..8be4fa9f1448171c0afb073274c1120a283747e3 100644 (file)
@@ -338,15 +338,19 @@ public abstract class OPCPackage implements RelationshipSource {
        }
 
        /**
-        * Close the package and save its content.
+        * Close the open, writable package and save its content.
+        * 
+        * If your package is open read only, then you should call {@link #revert()}
+        *  when finished with the package.
         *
         * @throws IOException
         *             If an IO exception occur during the saving process.
         */
        public void close() throws IOException {
                if (this.packageAccess == PackageAccess.READ) {
-                       logger
-                                       .log(POILogger.WARN, "The close() method is intended to SAVE a package. This package is open in READ ONLY mode, use the revert() method instead !");
+                       logger.log(POILogger.WARN, 
+                               "The close() method is intended to SAVE a package. This package is open in READ ONLY mode, use the revert() method instead !");
+                       revert();
                        return;
                }
 
@@ -1298,6 +1302,17 @@ public abstract class OPCPackage implements RelationshipSource {
                        throw new IllegalArgumentException("targetFile");
 
                this.throwExceptionIfReadOnly();
+               
+               // You shouldn't save the the same file, do a close instead
+               if(targetFile.exists() && 
+                       targetFile.getAbsolutePath().equals(this.originalPackagePath)) {
+                   throw new InvalidOperationException(
+                           "You can't call save(File) to save to the currently open " +
+                           "file. To save to the current file, please just call close()"
+                   );
+               }
+               
+               // Do the save
                FileOutputStream fos = null;
                try {
                        fos = new FileOutputStream(targetFile);
index 114c75c06eb0f64bd54b6f6310dbdb8b124c3182..52a871411e5b427890e23dfb90c6f570b8144ca4 100644 (file)
@@ -295,8 +295,11 @@ public final class ZipPackage extends Package {
                                // Save the final package to a temporary file
                                try {
                                        save(tempFile);
-                                       this.zipArchive.close(); // Close the zip archive to be
-                                       // able to delete it
+                                       
+                                       // Close the current zip file, so we can
+                                       //  overwrite it on all platforms
+                                       this.zipArchive.close();
+                                       // Copy the new file over the old one
                                        FileHelper.copyFile(tempFile, targetFile);
                                } finally {
                                        // Either the save operation succeed or not, we delete the
@@ -312,7 +315,7 @@ public final class ZipPackage extends Package {
                                throw new InvalidOperationException(
                                                "Can't close a package not previously open with the open() method !");
                        }
-               }
+               } 
        }
 
        /**
index 9bb66c0a41de506126acdb4678fcfcc4711705f3..4224317f43e64afaa2fdf28ba851d893e0f0056b 100644 (file)
@@ -32,6 +32,7 @@ import junit.framework.TestCase;
 
 import org.apache.poi.openxml4j.OpenXML4JTestDataSamples;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
 import org.apache.poi.openxml4j.opc.internal.ContentTypeManager;
 import org.apache.poi.openxml4j.opc.internal.FileHelper;
 import org.apache.poi.util.TempFile;
@@ -443,6 +444,64 @@ public final class TestPackage extends TestCase {
                // Don't save modifications
                p.revert();
        }
+       
+       /**
+        * Test that we can open a file by path, and then
+        *  write changes to it.
+        */
+       public void testOpenFileThenOverwrite() throws Exception {
+        File tempFile = File.createTempFile("poiTesting","tmp");
+        File origFile = OpenXML4JTestDataSamples.getSampleFile("TestPackageCommon.docx");
+        FileHelper.copyFile(origFile, tempFile);
+        
+        // Open the temp file
+        OPCPackage p = OPCPackage.open(tempFile.toString(), PackageAccess.READ_WRITE);
+        // Close it
+        p.close();
+        // Delete it
+        assertTrue(tempFile.delete());
+        
+        // Reset
+        FileHelper.copyFile(origFile, tempFile);
+        p = OPCPackage.open(tempFile.toString(), PackageAccess.READ_WRITE);
+        
+        // Save it to the same file - not allowed
+        try {
+            p.save(tempFile);
+            fail("You shouldn't be able to call save(File) to overwrite the current file");
+        } catch(InvalidOperationException e) {}
+        
+        // Delete it
+        assertTrue(tempFile.delete());
+        
+        
+        // Open it read only, then close and delete - allowed
+        FileHelper.copyFile(origFile, tempFile);
+        p = OPCPackage.open(tempFile.toString(), PackageAccess.READ);
+        p.close();
+        assertTrue(tempFile.delete());
+       }
+    /**
+     * Test that we can open a file by path, save it
+     *  to another file, then delete both
+     */
+    public void testOpenFileThenSaveDelete() throws Exception {
+        File tempFile = File.createTempFile("poiTesting","tmp");
+        File tempFile2 = File.createTempFile("poiTesting","tmp");
+        File origFile = OpenXML4JTestDataSamples.getSampleFile("TestPackageCommon.docx");
+        FileHelper.copyFile(origFile, tempFile);
+        
+        // Open the temp file
+        OPCPackage p = OPCPackage.open(tempFile.toString(), PackageAccess.READ_WRITE);
+
+        // Save it to a different file
+        p.save(tempFile2);
+        p.close();
+        
+        // Delete both the files
+        assertTrue(tempFile.delete());
+        assertTrue(tempFile2.delete());
+    }
 
        private static ContentTypeManager getContentTypeManager(OPCPackage pkg) throws Exception {
                Field f = OPCPackage.class.getDeclaredField("contentTypeManager");