You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TestPOIFSFileSystem.java 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.poifs.filesystem;
  16. import java.io.ByteArrayOutputStream;
  17. import java.io.File;
  18. import java.io.FileInputStream;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.util.Iterator;
  22. import junit.framework.TestCase;
  23. import org.apache.poi.POIDataSamples;
  24. import org.apache.poi.hssf.HSSFTestDataSamples;
  25. import org.apache.poi.poifs.common.POIFSBigBlockSize;
  26. import org.apache.poi.poifs.storage.HeaderBlockReader;
  27. import org.apache.poi.poifs.storage.RawDataBlockList;
  28. /**
  29. * Tests for POIFSFileSystem
  30. *
  31. * @author Josh Micich
  32. */
  33. public final class TestPOIFSFileSystem extends TestCase {
  34. /**
  35. * Mock exception used to ensure correct error handling
  36. */
  37. private static final class MyEx extends RuntimeException {
  38. public MyEx() {
  39. // no fields to initialise
  40. }
  41. }
  42. /**
  43. * Helps facilitate testing. Keeps track of whether close() was called.
  44. * Also can throw an exception at a specific point in the stream.
  45. */
  46. private static final class TestIS extends InputStream {
  47. private final InputStream _is;
  48. private final int _failIndex;
  49. private int _currentIx;
  50. private boolean _isClosed;
  51. public TestIS(InputStream is, int failIndex) {
  52. _is = is;
  53. _failIndex = failIndex;
  54. _currentIx = 0;
  55. _isClosed = false;
  56. }
  57. public int read() throws IOException {
  58. int result = _is.read();
  59. if(result >=0) {
  60. checkRead(1);
  61. }
  62. return result;
  63. }
  64. public int read(byte[] b, int off, int len) throws IOException {
  65. int result = _is.read(b, off, len);
  66. checkRead(result);
  67. return result;
  68. }
  69. private void checkRead(int nBytes) {
  70. _currentIx += nBytes;
  71. if(_failIndex > 0 && _currentIx > _failIndex) {
  72. throw new MyEx();
  73. }
  74. }
  75. public void close() throws IOException {
  76. _isClosed = true;
  77. _is.close();
  78. }
  79. public boolean isClosed() {
  80. return _isClosed;
  81. }
  82. }
  83. /**
  84. * Test for undesired behaviour observable as of svn revision 618865 (5-Feb-2008).
  85. * POIFSFileSystem was not closing the input stream.
  86. */
  87. public void testAlwaysClose() {
  88. TestIS testIS;
  89. // Normal case - read until EOF and close
  90. testIS = new TestIS(openSampleStream("13224.xls"), -1);
  91. try {
  92. new POIFSFileSystem(testIS);
  93. } catch (IOException e) {
  94. throw new RuntimeException(e);
  95. }
  96. assertTrue("input stream was not closed", testIS.isClosed());
  97. // intended to crash after reading 10000 bytes
  98. testIS = new TestIS(openSampleStream("13224.xls"), 10000);
  99. try {
  100. new POIFSFileSystem(testIS);
  101. fail("ex should have been thrown");
  102. } catch (IOException e) {
  103. throw new RuntimeException(e);
  104. } catch (MyEx e) {
  105. // expected
  106. }
  107. assertTrue("input stream was not closed", testIS.isClosed()); // but still should close
  108. }
  109. /**
  110. * Test for bug # 48898 - problem opening an OLE2
  111. * file where the last block is short (i.e. not a full
  112. * multiple of 512 bytes)
  113. *
  114. * As yet, this problem remains. One school of thought is
  115. * not not issue an EOF when we discover the last block
  116. * is short, but this seems a bit wrong.
  117. * The other is to fix the handling of the last block in
  118. * POIFS, since it seems to be slight wrong
  119. */
  120. public void testShortLastBlock() throws Exception {
  121. String[] files = new String[] {
  122. "ShortLastBlock.qwp", "ShortLastBlock.wps"
  123. };
  124. POIDataSamples _samples = POIDataSamples.getPOIFSInstance();
  125. for(int i=0; i<files.length; i++) {
  126. // Open the file up
  127. POIFSFileSystem fs = new POIFSFileSystem(
  128. _samples.openResourceAsStream(files[i])
  129. );
  130. // Write it into a temp output array
  131. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  132. fs.writeFilesystem(baos);
  133. // Check sizes
  134. }
  135. }
  136. /**
  137. * Check that we do the right thing when the list of which
  138. * sectors are BAT blocks points off the list of
  139. * sectors that exist in the file.
  140. */
  141. public void testFATandDIFATsectors() throws Exception {
  142. POIDataSamples _samples = POIDataSamples.getPOIFSInstance();
  143. // Open the file up
  144. try {
  145. POIFSFileSystem fs = new POIFSFileSystem(
  146. _samples.openResourceAsStream("ReferencesInvalidSectors.mpp")
  147. );
  148. fail("File is corrupt and shouldn't have been opened");
  149. } catch(IOException e) {
  150. String msg = e.getMessage();
  151. assertTrue(msg.startsWith("Your file contains 695 sectors"));
  152. }
  153. }
  154. /**
  155. * Most OLE2 files use 512byte blocks. However, a small number
  156. * use 4k blocks. Check that we can open these.
  157. */
  158. public void test4KBlocks() throws Exception {
  159. POIDataSamples _samples = POIDataSamples.getPOIFSInstance();
  160. InputStream inp = _samples.openResourceAsStream("BlockSize4096.zvi");
  161. // First up, check that we can process the header properly
  162. HeaderBlockReader header_block_reader = new HeaderBlockReader(inp);
  163. POIFSBigBlockSize bigBlockSize = header_block_reader.getBigBlockSize();
  164. assertEquals(4096, bigBlockSize.getBigBlockSize());
  165. // Check the fat info looks sane
  166. assertEquals(109, header_block_reader.getBATArray().length);
  167. assertTrue(header_block_reader.getBATCount() > 0);
  168. assertEquals(0, header_block_reader.getXBATCount());
  169. // Now check we can get the basic fat
  170. RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
  171. // Now try and open properly
  172. POIFSFileSystem fs = new POIFSFileSystem(
  173. _samples.openResourceAsStream("BlockSize4096.zvi")
  174. );
  175. assertTrue(fs.getRoot().getEntryCount() > 3);
  176. // Check we can get at all the contents
  177. checkAllDirectoryContents(fs.getRoot());
  178. // Finally, check we can do a similar 512byte one too
  179. fs = new POIFSFileSystem(
  180. _samples.openResourceAsStream("BlockSize512.zvi")
  181. );
  182. assertTrue(fs.getRoot().getEntryCount() > 3);
  183. checkAllDirectoryContents(fs.getRoot());
  184. }
  185. private void checkAllDirectoryContents(DirectoryEntry dir) throws IOException {
  186. for(Entry entry : dir) {
  187. if(entry instanceof DirectoryEntry) {
  188. checkAllDirectoryContents((DirectoryEntry)entry);
  189. } else {
  190. DocumentNode doc = (DocumentNode) entry;
  191. DocumentInputStream dis = new DocumentInputStream(doc);
  192. int numBytes = dis.available();
  193. byte[] data = new byte [numBytes];
  194. dis.read(data);
  195. }
  196. }
  197. }
  198. /**
  199. * Test that we can open files that come via Lotus notes.
  200. * These have a top level directory without a name....
  201. */
  202. public void testNotesOLE2Files() throws Exception {
  203. POIDataSamples _samples = POIDataSamples.getPOIFSInstance();
  204. // Open the file up
  205. POIFSFileSystem fs = new POIFSFileSystem(
  206. _samples.openResourceAsStream("Notes.ole2")
  207. );
  208. // Check the contents
  209. assertEquals(1, fs.getRoot().getEntryCount());
  210. Entry entry = fs.getRoot().getEntries().next();
  211. assertTrue(entry.isDirectoryEntry());
  212. assertTrue(entry instanceof DirectoryEntry);
  213. // The directory lacks a name!
  214. DirectoryEntry dir = (DirectoryEntry)entry;
  215. assertEquals("", dir.getName());
  216. // Has two children
  217. assertEquals(2, dir.getEntryCount());
  218. // Check them
  219. Iterator<Entry> it = dir.getEntries();
  220. entry = it.next();
  221. assertEquals(true, entry.isDocumentEntry());
  222. assertEquals("\u0001Ole10Native", entry.getName());
  223. entry = it.next();
  224. assertEquals(true, entry.isDocumentEntry());
  225. assertEquals("\u0001CompObj", entry.getName());
  226. }
  227. private static InputStream openSampleStream(String sampleFileName) {
  228. return HSSFTestDataSamples.openSampleFileStream(sampleFileName);
  229. }
  230. }