]> source.dussan.org Git - poi.git/commitdiff
Bug 57165: Avoid PartAlreadyExistsException when removing/cloning sheets
authorDominik Stadler <centic@apache.org>
Sun, 1 Mar 2015 19:56:56 +0000 (19:56 +0000)
committerDominik Stadler <centic@apache.org>
Sun, 1 Mar 2015 19:56:56 +0000 (19:56 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1663153 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java
src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java
src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePart.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestUnfixedBugs.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java

index 24b4af238984e65c235575b04fe3fdff04d5cb42..4759ddbd3b78ff9b36764add926d0a20aa0da88f 100644 (file)
@@ -349,11 +349,27 @@ public class POIXMLDocumentPart {
      * @param descriptor the part descriptor
      * @param factory the factory that will create an instance of the requested relation
      * @return the created child POIXMLDocumentPart
+     * @throws PartAlreadyExistsException
+     *             If rule M1.12 is not verified : Packages shall not contain
+     *             equivalent part names and package implementers shall neither
+     *             create nor recognize packages with equivalent part names.
      */
     public final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory){
         return createRelationship(descriptor, factory, -1, false);
     }
 
+    /**
+     * Create a new child POIXMLDocumentPart
+     *
+     * @param descriptor the part descriptor
+     * @param factory the factory that will create an instance of the requested relation
+     * @param idx part number
+     * @return the created child POIXMLDocumentPart
+     * @throws PartAlreadyExistsException
+     *             If rule M1.12 is not verified : Packages shall not contain
+     *             equivalent part names and package implementers shall neither
+     *             create nor recognize packages with equivalent part names.
+     */
     public final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx){
         return createRelationship(descriptor, factory, idx, false);
     }
@@ -366,6 +382,10 @@ public class POIXMLDocumentPart {
      * @param idx part number
      * @param noRelation if true, then no relationship is added.
      * @return the created child POIXMLDocumentPart
+     * @throws PartAlreadyExistsException
+     *             If rule M1.12 is not verified : Packages shall not contain
+     *             equivalent part names and package implementers shall neither
+     *             create nor recognize packages with equivalent part names.
      */
     protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx, boolean noRelation){
         try {
index e210be6f674b7753ef415dd0a53c35d2e640328a..4f3d6ca6508dd8bc65083486b62f2e099e0a0dfa 100644 (file)
@@ -739,7 +739,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
         * @param contentType
         *            Part content type.
         * @return The newly created part.
-        * @throws InvalidFormatException
+        * @throws PartAlreadyExistsException
         *             If rule M1.12 is not verified : Packages shall not contain
         *             equivalent part names and package implementers shall neither
         *             create nor recognize packages with equivalent part names.
@@ -762,7 +762,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
         *            Specify if the existing relationship part, if any, logically
         *            associated to the newly created part will be loaded.
         * @return The newly created part.
-        * @throws InvalidFormatException
+        * @throws PartAlreadyExistsException
         *             If rule M1.12 is not verified : Packages shall not contain
         *             equivalent part names and package implementers shall neither
         *             create nor recognize packages with equivalent part names.
index 8b72770a774d53782f7cf3050c114783d9a486b9..8cfdb0fb3649720e2482c76231477b5c28190ecb 100644 (file)
@@ -228,8 +228,13 @@ public abstract class PackagePart implements RelationshipSource {
         *            Relationship unique id.
         * @return The newly created and added relationship
         *
+        * @throws InvalidOperationException
+        *             If a writing operation is done on a read only package or 
+        *             invalid nested relations are created.
         * @throws InvalidFormatException
         *             If the URI point to a relationship part URI.
+        * @throws IllegalArgumentException if targetPartName, targetMode 
+        *             or relationshipType are passed as null
         * @see org.apache.poi.openxml4j.opc.RelationshipSource#addRelationship(org.apache.poi.openxml4j.opc.PackagePartName,
         *      org.apache.poi.openxml4j.opc.TargetMode, java.lang.String, java.lang.String)
         */
index ae09af141df67a3f39b0bc9ac4fe353ce37e9432..41a6d613ffbeccc43a9dcc9ee4d172effebe6b12 100644 (file)
@@ -751,8 +751,26 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
         CTSheet sheet = addSheet(sheetname);
 
         int sheetNumber = 1;
-        for(XSSFSheet sh : sheets) {
-            sheetNumber = (int)Math.max(sh.sheet.getSheetId() + 1, sheetNumber);
+        outerloop:
+        while(true) {
+            for(XSSFSheet sh : sheets) {
+                sheetNumber = (int)Math.max(sh.sheet.getSheetId() + 1, sheetNumber);
+            }
+            
+            // Bug 57165: We also need to check that the resulting file name is not already taken
+            // this can happen when moving/cloning sheets
+            String sheetName = XSSFRelation.WORKSHEET.getFileName(sheetNumber);
+            for(POIXMLDocumentPart relation : getRelations()) {
+                if(relation.getPackagePart() != null && 
+                        sheetName.equals(relation.getPackagePart().getPartName().getName())) {
+                    // name is taken => try next one
+                    sheetNumber++;
+                    continue outerloop;
+                }
+            }
+
+            // no duplicate found => use this one
+            break;
         }
 
         XSSFSheet wrapper = (XSSFSheet)createRelationship(XSSFRelation.WORKSHEET, XSSFFactory.getInstance(), sheetNumber);
index c90ba80614b5b2b226dcbeeeed57211adc83afe5..0e5864b365f9256d868a902dfb7f88affa27d089 100644 (file)
@@ -17,8 +17,6 @@
 \r
 package org.apache.poi.xssf.usermodel;\r
 \r
-import static org.junit.Assert.assertEquals;\r
-\r
 import java.io.IOException;\r
 import java.nio.charset.Charset;\r
 import java.util.Calendar;\r
@@ -184,38 +182,6 @@ public final class TestUnfixedBugs extends TestCase {
         }\r
     }\r
 \r
-    \r
-    @Test\r
-    public void test57165() throws IOException {\r
-        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("57171_57163_57165.xlsx");\r
-        try {\r
-            removeAllSheetsBut(3, wb);\r
-            wb.cloneSheet(0); // Throws exception here\r
-            wb.setSheetName(1, "New Sheet");\r
-            //saveWorkbook(wb, fileName);\r
-            \r
-            XSSFWorkbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb);\r
-            try {\r
-                \r
-            } finally {\r
-                wbBack.close();\r
-            }\r
-        } finally {\r
-            wb.close();\r
-        }\r
-    }\r
-\r
-    private static void removeAllSheetsBut(int sheetIndex, Workbook wb)\r
-    {\r
-        int sheetNb = wb.getNumberOfSheets();\r
-        // Move this sheet at the first position\r
-        wb.setSheetOrder(wb.getSheetName(sheetIndex), 0);\r
-        for (int sn = sheetNb - 1; sn > 0; sn--)\r
-        {\r
-            wb.removeSheetAt(sn);\r
-        }\r
-    }\r
-\r
     // When this is fixed, the test case should go to BaseTestXCell with \r
     // adjustments to use _testDataProvider to also verify this for XSSF\r
     public void testBug57294() throws IOException {\r
index 0f8549562d474755d97b28db4eac274ac6d2270b..1ebb56178a453a2fd1c1938058fc79f1e19cf9d6 100644 (file)
@@ -2134,4 +2134,36 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
         assertEquals("~CIRCULAR~REF~", FormulaError.forInt(value.getErrorValue()).getString());
         assertEquals("CIRCULAR_REF", FormulaError.forInt(value.getErrorValue()).toString());
     }
+
+    
+    @Test
+    public void test57165() throws IOException {
+        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("57171_57163_57165.xlsx");
+        try {
+            removeAllSheetsBut(3, wb);
+            wb.cloneSheet(0); // Throws exception here
+            wb.setSheetName(1, "New Sheet");
+            //saveWorkbook(wb, fileName);
+            
+            XSSFWorkbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb);
+            try {
+                
+            } finally {
+                wbBack.close();
+            }
+        } finally {
+            wb.close();
+        }
+    }
+
+    private static void removeAllSheetsBut(int sheetIndex, Workbook wb)
+    {
+        int sheetNb = wb.getNumberOfSheets();
+        // Move this sheet at the first position
+        wb.setSheetOrder(wb.getSheetName(sheetIndex), 0);
+        for (int sn = sheetNb - 1; sn > 0; sn--)
+        {
+            wb.removeSheetAt(sn);
+        }
+    }
 }