]> source.dussan.org Git - poi.git/commitdiff
Bugzilla 47001 - Fixed WriteAccessRecord and LinkTable to handle unusual format writt...
authorJosh Micich <josh@apache.org>
Wed, 8 Apr 2009 21:01:43 +0000 (21:01 +0000)
committerJosh Micich <josh@apache.org>
Wed, 8 Apr 2009 21:01:43 +0000 (21:01 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@763391 13f79535-47bb-0310-9956-ffa450edef68

15 files changed:
src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/model/LinkTable.java
src/java/org/apache/poi/hssf/record/WriteAccessRecord.java
src/testcases/org/apache/poi/hssf/data/42564-2.xls [deleted file]
src/testcases/org/apache/poi/hssf/data/42564.xls [deleted file]
src/testcases/org/apache/poi/hssf/data/ex42564-21435.xls [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/data/ex42564-21503.xls [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/model/AllModelTests.java
src/testcases/org/apache/poi/hssf/model/TestLinkTable.java [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/record/AllRecordTests.java
src/testcases/org/apache/poi/hssf/record/TestWriteAccessRecord.java [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/usermodel/AllUserModelTests.java
src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
src/testcases/org/apache/poi/hssf/usermodel/TestLinkTable.java [deleted file]

index 4929d519e6bee7acdfb48632b2fd44fd1e8a6ac3..e2f50b9ad6e41c551979ba4393389caea6a1b228 100644 (file)
@@ -37,6 +37,7 @@
 
                <!-- Don't forget to update status.xml too! -->
         <release version="3.5-beta6" date="2009-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">47001 - Fixed WriteAccessRecord and LinkTable to handle unusual format written by Google Docs</action>
            <action dev="POI-DEVELOPERS" type="fix">46973 - Fixed defined names to behave better when refersToFormula is unset</action>
            <action dev="POI-DEVELOPERS" type="fix">46832 - Allow merged regions with columns greater than 255 or rows bigger than 65536 in XSSF</action>
            <action dev="POI-DEVELOPERS" type="fix">46951 - Fixed formula parser to better handle range operators and whole row/column refs.</action>
index 8077cd8de29165260aa0881171c1bbb5d7464cc7..99095f13f2c25f71ad924dc4a0a99a3184ad3e89 100644 (file)
@@ -34,6 +34,7 @@
        <!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.5-beta6" date="2009-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">47001 - Fixed WriteAccessRecord and LinkTable to handle unusual format written by Google Docs</action>
            <action dev="POI-DEVELOPERS" type="fix">46973 - Fixed defined names to behave better when refersToFormula is unset</action>
            <action dev="POI-DEVELOPERS" type="fix">46832 - Allow merged regions with columns greater than 255 or rows bigger than 65536 in XSSF</action>
            <action dev="POI-DEVELOPERS" type="fix">46951 - Fixed formula parser to better handle range operators and whole row/column refs.</action>
index f587f5e375c478b416b79f9b26d91aad2df995c9..f5c44ce5c913deb5456cb613e117db89083a1300 100755 (executable)
@@ -161,7 +161,12 @@ final class LinkTable {
                
                if (_externalBookBlocks.length > 0) {
                        // If any ExternalBookBlock present, there is always 1 of ExternSheetRecord
-                       _externSheetRecord = readExtSheetRecord(rs);
+                       if (rs.peekNextClass() != ExternSheetRecord.class) {
+                               // not quite - if written by google docs
+                               _externSheetRecord = null;
+                       } else {
+                               _externSheetRecord = readExtSheetRecord(rs);
+                       }
                } else {
                        _externSheetRecord = null;
                }
index 3ff094e7f6d23a23896e62970da5a3ce688c9d46..f87373b1ab5165c10e9ac8b401747261473bc16c 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.poi.hssf.record;
 
 import java.util.Arrays;
 
+import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianOutput;
 import org.apache.poi.util.StringUtil;
 
@@ -40,11 +41,13 @@ public final class WriteAccessRecord extends StandardRecord {
        private static final int DATA_SIZE = 112;
        private String field_1_username;
        /** this record is always padded to a constant length */
-       private byte[] padding;
+       private static final byte[] PADDING = new byte[DATA_SIZE];
+       static {
+               Arrays.fill(PADDING, PAD_CHAR);
+       }
 
        public WriteAccessRecord() {
                setUsername("");
-               padding = new byte[DATA_SIZE - 3];
        }
 
        public WriteAccessRecord(RecordInputStream in) {
@@ -57,21 +60,33 @@ public final class WriteAccessRecord extends StandardRecord {
 
                int nChars = in.readUShort();
                int is16BitFlag = in.readUByte();
-               int expectedPadSize = DATA_SIZE - 3;
+               if (nChars > DATA_SIZE || (is16BitFlag & 0xFE) != 0) {
+                       // String header looks wrong (probably missing)
+                       // OOO doc says this is optional anyway.
+                       // reconstruct data
+                       byte[] data = new byte[3 + in.remaining()];
+                       LittleEndian.putUShort(data, 0, nChars);
+                       LittleEndian.putByte(data, 2, is16BitFlag);
+                       in.readFully(data, 3, data.length-3);
+                       String rawValue = new String(data);
+                       setUsername(rawValue.trim());
+                       return;
+               }
+
+               String rawText;
                if ((is16BitFlag & 0x01) == 0x00) {
-                       field_1_username = StringUtil.readCompressedUnicode(in, nChars);
-                       expectedPadSize -= nChars;
+                       rawText = StringUtil.readCompressedUnicode(in, nChars);
                } else {
-                       field_1_username = StringUtil.readUnicodeLE(in, nChars);
-                       expectedPadSize -= nChars * 2;
+                       rawText = StringUtil.readUnicodeLE(in, nChars);
                }
-               padding = new byte[expectedPadSize];
+               field_1_username = rawText.trim();
+
+               // consume padding
                int padSize = in.remaining();
-               in.readFully(padding, 0, padSize);
-               if (padSize < expectedPadSize) {
-                       // this occurs in a couple of test examples: "42564.xls",
-                       // "bug_42794.xls"
-                       Arrays.fill(padding, padSize, expectedPadSize, PAD_CHAR);
+               while (padSize > 0) {
+                       // in some cases this seems to be garbage (non spaces)
+                       in.readUByte();
+                       padSize--;
                }
        }
 
@@ -88,8 +103,6 @@ public final class WriteAccessRecord extends StandardRecord {
                if (paddingSize < 0) {
                        throw new IllegalArgumentException("Name is too long: " + username);
                }
-               padding = new byte[paddingSize];
-               Arrays.fill(padding, PAD_CHAR);
 
                field_1_username = username;
        }
@@ -109,7 +122,7 @@ public final class WriteAccessRecord extends StandardRecord {
                StringBuffer buffer = new StringBuffer();
 
                buffer.append("[WRITEACCESS]\n");
-               buffer.append("    .name            = ").append(field_1_username.toString()).append("\n");
+               buffer.append("    .name = ").append(field_1_username.toString()).append("\n");
                buffer.append("[/WRITEACCESS]\n");
                return buffer.toString();
        }
@@ -125,7 +138,9 @@ public final class WriteAccessRecord extends StandardRecord {
                } else {
                        StringUtil.putCompressedUnicode(username, out);
                }
-               out.write(padding);
+               int encodedByteCount = 3 + username.length() * (is16bit ? 2 : 1);
+               int paddingSize = DATA_SIZE - encodedByteCount;
+               out.write(PADDING, 0, paddingSize);
        }
 
        protected int getDataSize() {
diff --git a/src/testcases/org/apache/poi/hssf/data/42564-2.xls b/src/testcases/org/apache/poi/hssf/data/42564-2.xls
deleted file mode 100644 (file)
index 3a93b40..0000000
Binary files a/src/testcases/org/apache/poi/hssf/data/42564-2.xls and /dev/null differ
diff --git a/src/testcases/org/apache/poi/hssf/data/42564.xls b/src/testcases/org/apache/poi/hssf/data/42564.xls
deleted file mode 100644 (file)
index dff150e..0000000
Binary files a/src/testcases/org/apache/poi/hssf/data/42564.xls and /dev/null differ
diff --git a/src/testcases/org/apache/poi/hssf/data/ex42564-21435.xls b/src/testcases/org/apache/poi/hssf/data/ex42564-21435.xls
new file mode 100644 (file)
index 0000000..dff150e
Binary files /dev/null and b/src/testcases/org/apache/poi/hssf/data/ex42564-21435.xls differ
diff --git a/src/testcases/org/apache/poi/hssf/data/ex42564-21503.xls b/src/testcases/org/apache/poi/hssf/data/ex42564-21503.xls
new file mode 100644 (file)
index 0000000..3a93b40
Binary files /dev/null and b/src/testcases/org/apache/poi/hssf/data/ex42564-21503.xls differ
index 35565a7a6583a3a9e897c4e190ff50159a4d2f2b..a243226867050038531363f1cf479651e3eb2fe6 100755 (executable)
@@ -34,6 +34,7 @@ public final class AllModelTests {
                result.addTestSuite(TestFormulaParser.class);
                result.addTestSuite(TestFormulaParserEval.class);
                result.addTestSuite(TestFormulaParserIf.class);
+               result.addTestSuite(TestLinkTable.class);
                result.addTestSuite(TestOperandClassTransformer.class);
                result.addTestSuite(TestRowBlocksReader.class);
                result.addTestSuite(TestRVA.class);
diff --git a/src/testcases/org/apache/poi/hssf/model/TestLinkTable.java b/src/testcases/org/apache/poi/hssf/model/TestLinkTable.java
new file mode 100644 (file)
index 0000000..f88cd48
--- /dev/null
@@ -0,0 +1,151 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.model;
+
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.record.Record;
+import org.apache.poi.hssf.record.SSTRecord;
+import org.apache.poi.hssf.record.SupBookRecord;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+/**
+ * Tests for {@link LinkTable}
+ *
+ * @author Josh Micich
+ */
+public final class TestLinkTable extends TestCase {
+
+       /**
+        * The example file attached to bugzilla 45046 is a clear example of Name records being present
+        * without an External Book (SupBook) record.  Excel has no trouble reading this file.<br/>
+        * TODO get OOO documentation updated to reflect this (that EXTERNALBOOK is optional).
+        *
+        * It's not clear what exact steps need to be taken in Excel to create such a workbook
+        */
+       public void testLinkTableWithoutExternalBookRecord_bug45046() {
+               HSSFWorkbook wb;
+
+               try {
+                       wb = HSSFTestDataSamples.openSampleWorkbook("ex45046-21984.xls");
+               } catch (RuntimeException e) {
+                       if ("DEFINEDNAME is part of LinkTable".equals(e.getMessage())) {
+                               throw new AssertionFailedError("Identified bug 45046 b");
+                       }
+                       throw e;
+               }
+               // some other sanity checks
+               assertEquals(3, wb.getNumberOfSheets());
+               String formula = wb.getSheetAt(0).getRow(4).getCell(13).getCellFormula();
+
+               if ("ipcSummenproduktIntern($P5,N$6,$A$9,N$5)".equals(formula)) {
+                       // The reported symptom of this bugzilla is an earlier bug (already fixed)
+                       throw new AssertionFailedError("Identified bug 41726");
+                       // This is observable in version 3.0
+               }
+
+               assertEquals("ipcSummenproduktIntern($C5,N$2,$A$9,N$1)", formula);
+       }
+
+       public void testMultipleExternSheetRecords_bug45698() {
+               HSSFWorkbook wb;
+
+               try {
+                       wb = HSSFTestDataSamples.openSampleWorkbook("ex45698-22488.xls");
+               } catch (RuntimeException e) {
+                       if ("Extern sheet is part of LinkTable".equals(e.getMessage())) {
+                               throw new AssertionFailedError("Identified bug 45698");
+                       }
+                       throw e;
+               }
+               // some other sanity checks
+               assertEquals(7, wb.getNumberOfSheets());
+       }
+
+       public void testExtraSheetRefs_bug45978() {
+               HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ex45978-extraLinkTableSheets.xls");
+               /*
+               ex45978-extraLinkTableSheets.xls is a cut-down version of attachment 22561.
+               The original file produces the same error.
+
+               This bug was caused by a combination of invalid sheet indexes in the EXTERNSHEET
+               record, and eager initialisation of the extern sheet references. Note - the workbook
+               has 2 sheets, but the EXTERNSHEET record refers to sheet indexes 0, 1 and 2.
+
+               Offset 0x3954 (14676)
+               recordid = 0x17, size = 32
+               [EXTERNSHEET]
+                  numOfRefs     = 5
+               refrec           #0: extBook=0 firstSheet=0 lastSheet=0
+               refrec           #1: extBook=1 firstSheet=2 lastSheet=2
+               refrec           #2: extBook=2 firstSheet=1 lastSheet=1
+               refrec           #3: extBook=0 firstSheet=-1 lastSheet=-1
+               refrec           #4: extBook=0 firstSheet=1 lastSheet=1
+               [/EXTERNSHEET]
+
+               As it turns out, the formula in question doesn't even use externSheetIndex #1 - it
+               uses #4, which resolves to sheetIndex 1 -> 'Data'.
+
+               It is not clear exactly what externSheetIndex #4 would refer to.  Excel seems to
+               display such a formula as "''!$A2", but then complains of broken link errors.
+               */
+
+               HSSFCell cell = wb.getSheetAt(0).getRow(1).getCell(1);
+               String cellFormula;
+               try {
+                       cellFormula = cell.getCellFormula();
+               } catch (IndexOutOfBoundsException e) {
+                       if (e.getMessage().equals("Index: 2, Size: 2")) {
+                               throw new AssertionFailedError("Identified bug 45798");
+                       }
+                       throw e;
+               }
+               assertEquals("Data!$A2", cellFormula);
+       }
+
+       /**
+        * This problem was visible in POI svn r763332
+        * when reading the workbook of attachment 23468 from bugzilla 47001
+        */
+       public void testMissingExternSheetRecord_bug47001b() {
+               
+               Record[] recs = {
+                               SupBookRecord.createAddInFunctions(),
+                               new SSTRecord(),
+               };
+               List<Record> recList = Arrays.asList(recs);
+               WorkbookRecordList wrl = new WorkbookRecordList();
+               
+               LinkTable lt;
+               try {
+                       lt = new LinkTable(recList, 0, wrl);
+               } catch (RuntimeException e) {
+                       if (e.getMessage().equals("Expected an EXTERNSHEET record but got (org.apache.poi.hssf.record.SSTRecord)")) {
+                               throw new AssertionFailedError("Identified bug 47001b");
+                       }
+               
+                       throw e;
+               }
+               assertNotNull(lt);
+       }       
+}
index 3458051ee74129e01a0ff187a78487309ee848a2..e7d8c7f4a549182878e53b3aa50424d258b88aed 100755 (executable)
@@ -80,6 +80,7 @@ public final class AllRecordTests {
                result.addTestSuite(TestTextObjectRecord.class);
                result.addTestSuite(TestUnicodeNameRecord.class);
                result.addTestSuite(TestUnicodeString.class);
+               result.addTestSuite(TestWriteAccessRecord.class);
                result.addTestSuite(TestCellRange.class);
                result.addTestSuite(TestConstantValueParser.class);
                return result;
diff --git a/src/testcases/org/apache/poi/hssf/record/TestWriteAccessRecord.java b/src/testcases/org/apache/poi/hssf/record/TestWriteAccessRecord.java
new file mode 100644 (file)
index 0000000..8d170c0
--- /dev/null
@@ -0,0 +1,103 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+        \r
+package org.apache.poi.hssf.record;\r
+\r
+import junit.framework.AssertionFailedError;\r
+import junit.framework.TestCase;\r
+\r
+import org.apache.poi.util.HexRead;\r
+\r
+/**\r
+ * Tests for {@link WriteAccessRecord}\r
+ *\r
+ * @author Josh Micich\r
+ */\r
+public final class TestWriteAccessRecord extends TestCase {\r
+    \r
+       private static final String HEX_SIXTYFOUR_SPACES = ""\r
+               + "20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 "\r
+               + "20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 "\r
+               + "20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 "\r
+               + "20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20";\r
+               \r
+       \r
+       public void testMissingStringHeader_bug47001a() {\r
+               /*\r
+                * Data taken from offset 0x0224 in\r
+                * attachment 23468 from bugzilla 47001\r
+                */\r
+               byte[] data = HexRead.readFromString(""\r
+                               + "5C 00 70 00 "\r
+                               + "4A 61 76 61 20 45 78 63 65 6C 20 41 50 49 20 76 "\r
+                               + "32 2E 36 2E 34"\r
+                               +                "20 20 20 20 20 20 20 20 20 20 20 "\r
+                               + "20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 "\r
+                               + HEX_SIXTYFOUR_SPACES);\r
+\r
+               RecordInputStream in = TestcaseRecordInputStream.create(data);\r
+\r
+               WriteAccessRecord rec;\r
+               try {\r
+                       rec = new WriteAccessRecord(in);\r
+               } catch (RecordFormatException e) {\r
+                       if (e.getMessage().equals("Not enough data (0) to read requested (1) bytes")) {\r
+                               throw new AssertionFailedError("Identified bug 47001a");\r
+                       }\r
+                       throw e;\r
+               }\r
+               assertEquals("Java Excel API v2.6.4", rec.getUsername());\r
+               \r
+               \r
+               byte[] expectedEncoding = HexRead.readFromString(""\r
+                               + "15 00 00 4A 61 76 61 20 45 78 63 65 6C 20 41 50 "\r
+                               + "49 20 76 32 2E 36 2E 34"\r
+                               +                         "20 20 20 20 20 20 20 20 "\r
+                               + "20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 "\r
+                               + HEX_SIXTYFOUR_SPACES);\r
+               \r
+               TestcaseRecordInputStream.confirmRecordEncoding(WriteAccessRecord.sid, expectedEncoding, rec.serialize());\r
+       }\r
+       \r
+       public void testShortRecordWrittenByMSAccess() {\r
+               /*\r
+                * Data taken from two example files\r
+                * ex42564-21435.xls \r
+                * bug_42794.xls (from bug 42794 attachment 20429)\r
+                * In both cases, this data is found at offset 0x0C1C.\r
+                */\r
+               byte[] data = HexRead.readFromString(""\r
+                               + "5C 00 39 00 "\r
+                               + "36 00 00 41 20 73 61 74 69 73 66 69 65 64 20 4D "\r
+                               + "69 63 72 6F 73 6F 66 74 20 4F 66 66 69 63 65 39 "\r
+                               + "20 55 73 65 72"\r
+                               +                "20 20 20 20 20 20 20 20 20 20 20 "\r
+                               + "20 20 20 20 20 20 20 20 20");\r
+\r
+               RecordInputStream in = TestcaseRecordInputStream.create(data);\r
+               WriteAccessRecord rec = new WriteAccessRecord(in);\r
+               assertEquals("A satisfied Microsoft Office9 User", rec.getUsername());\r
+               byte[] expectedEncoding = HexRead.readFromString(""\r
+                               + "22 00 00 41 20 73 61 74 69 73 66 69 65 64 20 4D "\r
+                               + "69 63 72 6F 73 6F 66 74 20 4F 66 66 69 63 65 39 "\r
+                               + "20 55 73 65 72"\r
+                               +                "20 20 20 20 20 20 20 20 20 20 20 "\r
+                               + HEX_SIXTYFOUR_SPACES);\r
+               \r
+               TestcaseRecordInputStream.confirmRecordEncoding(WriteAccessRecord.sid, expectedEncoding, rec.serialize());\r
+       }\r
+}\r
index 6b3043c07280b78edacccfd57f9eb75267eb0030..eec05641afc2c2cc18a762b3468196e2ffb741f7 100755 (executable)
@@ -59,7 +59,6 @@ public class AllUserModelTests {
                result.addTestSuite(TestHSSFSheet.class);
                result.addTestSuite(TestHSSFTextbox.class);
                result.addTestSuite(TestHSSFWorkbook.class);
-               result.addTestSuite(TestLinkTable.class);
                result.addTestSuite(TestHSSFName.class);
                result.addTestSuite(TestOLE2Embeding.class);
                result.addTestSuite(TestPOIFSProperties.class);
index 44063e3c7a321953bb7ab7bd0611f8a59a966d4c..d81441c003ebd7fffdec4d06eb32298f3e88f49b 100644 (file)
@@ -586,7 +586,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
      *  when reading the BOFRecord
      */
     public void test42564() {
-        HSSFWorkbook wb = openSample("42564.xls");
+        HSSFWorkbook wb = openSample("ex42564-21435.xls");
         writeOutAndReadBack(wb);
     }
 
@@ -596,7 +596,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
      *  issue.
      */
     public void test42564Alt() {
-        HSSFWorkbook wb = openSample("42564-2.xls");
+        HSSFWorkbook wb = openSample("ex42564-21503.xls");
         writeOutAndReadBack(wb);
     }
 
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestLinkTable.java b/src/testcases/org/apache/poi/hssf/usermodel/TestLinkTable.java
deleted file mode 100644 (file)
index 5a96960..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-==================================================================== */
-
-package org.apache.poi.hssf.usermodel;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-/**
- * Tests for {@link LinkTable}
- *
- * @author Josh Micich
- */
-public final class TestLinkTable extends TestCase {
-
-       /**
-        * The example file attached to bugzilla 45046 is a clear example of Name records being present
-        * without an External Book (SupBook) record.  Excel has no trouble reading this file.<br/>
-        * TODO get OOO documentation updated to reflect this (that EXTERNALBOOK is optional).
-        *
-        * It's not clear what exact steps need to be taken in Excel to create such a workbook
-        */
-       public void testLinkTableWithoutExternalBookRecord_bug45046() {
-               HSSFWorkbook wb;
-
-               try {
-                       wb = HSSFTestDataSamples.openSampleWorkbook("ex45046-21984.xls");
-               } catch (RuntimeException e) {
-                       if ("DEFINEDNAME is part of LinkTable".equals(e.getMessage())) {
-                               throw new AssertionFailedError("Identified bug 45046 b");
-                       }
-                       throw e;
-               }
-               // some other sanity checks
-               assertEquals(3, wb.getNumberOfSheets());
-               String formula = wb.getSheetAt(0).getRow(4).getCell(13).getCellFormula();
-
-               if ("ipcSummenproduktIntern($P5,N$6,$A$9,N$5)".equals(formula)) {
-                       // The reported symptom of this bugzilla is an earlier bug (already fixed)
-                       throw new AssertionFailedError("Identified bug 41726");
-                       // This is observable in version 3.0
-               }
-
-               assertEquals("ipcSummenproduktIntern($C5,N$2,$A$9,N$1)", formula);
-       }
-
-       public void testMultipleExternSheetRecords_bug45698() {
-               HSSFWorkbook wb;
-
-               try {
-                       wb = HSSFTestDataSamples.openSampleWorkbook("ex45698-22488.xls");
-               } catch (RuntimeException e) {
-                       if ("Extern sheet is part of LinkTable".equals(e.getMessage())) {
-                               throw new AssertionFailedError("Identified bug 45698");
-                       }
-                       throw e;
-               }
-               // some other sanity checks
-               assertEquals(7, wb.getNumberOfSheets());
-       }
-
-       public void testExtraSheetRefs_bug45978() {
-               HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ex45978-extraLinkTableSheets.xls");
-               /*
-               ex45978-extraLinkTableSheets.xls is a cut-down version of attachment 22561.
-               The original file produces the same error.
-
-               This bug was caused by a combination of invalid sheet indexes in the EXTERNSHEET
-               record, and eager initialisation of the extern sheet references. Note - the worbook
-               has 2 sheets, but the EXTERNSHEET record refers to sheet indexes 0, 1 and 2.
-
-               Offset 0x3954 (14676)
-               recordid = 0x17, size = 32
-               [EXTERNSHEET]
-                  numOfRefs     = 5
-               refrec           #0: extBook=0 firstSheet=0 lastSheet=0
-               refrec           #1: extBook=1 firstSheet=2 lastSheet=2
-               refrec           #2: extBook=2 firstSheet=1 lastSheet=1
-               refrec           #3: extBook=0 firstSheet=-1 lastSheet=-1
-               refrec           #4: extBook=0 firstSheet=1 lastSheet=1
-               [/EXTERNSHEET]
-
-               As it turns out, the formula in question doesn't even use externSheetIndex #1 - it
-               uses #4, which resolves to sheetIndex 1 -> 'Data'.
-
-               It is not clear exactly what externSheetIndex #4 would refer to.  Excel seems to
-               display such a formula as "''!$A2", but then complains of broken link errors.
-               */
-
-               HSSFCell cell = wb.getSheetAt(0).getRow(1).getCell(1);
-               String cellFormula;
-               try {
-                       cellFormula = cell.getCellFormula();
-               } catch (IndexOutOfBoundsException e) {
-                       if (e.getMessage().equals("Index: 2, Size: 2")) {
-                               throw new AssertionFailedError("Identified bug 45798");
-                       }
-                       throw e;
-               }
-               assertEquals("Data!$A2", cellFormula);
-       }
-}