]> source.dussan.org Git - poi.git/commitdiff
Add WorkbookFactory.create() with a flag to allow to open files read-only, keep the...
authorDominik Stadler <centic@apache.org>
Tue, 26 May 2015 19:30:21 +0000 (19:30 +0000)
committerDominik Stadler <centic@apache.org>
Tue, 26 May 2015 19:30:21 +0000 (19:30 +0000)
Also adjust Javadoc somewhat.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1681823 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/ss/usermodel/WorkbookFactory.java
src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java

index 3f5d5ea8351dd6cb3689f880defa5d3b84418b4f..dfdf3f92eca4f0e731b123ac309bfabefd12b81b 100644 (file)
@@ -30,6 +30,7 @@ import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackageAccess;
 import org.apache.poi.poifs.crypt.Decryptor;
 import org.apache.poi.poifs.crypt.EncryptionInfo;
 import org.apache.poi.poifs.filesystem.DirectoryNode;
@@ -41,22 +42,22 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 
 /**
  * Factory for creating the appropriate kind of Workbook
- *  (be it {@link HSSFWorkbook} or {@link XSSFWorkbook}), 
+ *  (be it {@link HSSFWorkbook} or {@link XSSFWorkbook}),
  *  by auto-detecting from the supplied input.
  */
 public class WorkbookFactory {
     /**
      * Creates a HSSFWorkbook from the given POIFSFileSystem
-     * <p>Note that in order to properly release resources the 
+     * <p>Note that in order to properly release resources the
      *  Workbook should be closed after use.
      */
     public static Workbook create(POIFSFileSystem fs) throws IOException {
         return new HSSFWorkbook(fs);
     }
-    
+
     /**
      * Creates a HSSFWorkbook from the given NPOIFSFileSystem
-     * <p>Note that in order to properly release resources the 
+     * <p>Note that in order to properly release resources the
      *  Workbook should be closed after use.
      */
     public static Workbook create(NPOIFSFileSystem fs) throws IOException {
@@ -67,19 +68,27 @@ public class WorkbookFactory {
             throw new IOException(e);
         }
     }
-    
+
     /**
      * Creates a Workbook from the given NPOIFSFileSystem, which may
      *  be password protected
+     *
+     *  @param fs The {@link NPOIFSFileSystem} to read the document from
+     *  @param password The password that should be used or null if no password is necessary.
+     *
+     *  @return The created Workbook
+     *
+     *  @throws IOException if an error occurs while reading the data
+     *  @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link Workbook}
      */
     private static Workbook create(NPOIFSFileSystem fs, String password) throws IOException, InvalidFormatException {
         DirectoryNode root = fs.getRoot();
-        
+
         // Encrypted OOXML files go inside OLE2 containers, is this one?
         if (root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) {
             EncryptionInfo info = new EncryptionInfo(fs);
             Decryptor d = Decryptor.getInstance(info);
-            
+
             boolean passwordCorrect = false;
             InputStream stream = null;
             try {
@@ -95,18 +104,18 @@ public class WorkbookFactory {
             } catch (GeneralSecurityException e) {
                 throw new IOException(e);
             }
-            
+
             if (! passwordCorrect) {
                 if (password != null)
                     throw new EncryptedDocumentException("Password incorrect");
                 else
                     throw new EncryptedDocumentException("The supplied spreadsheet is protected, but no password was supplied");
             }
-            
+
             OPCPackage pkg = OPCPackage.open(stream);
             return create(pkg);
         }
-        
+
         // If we get here, it isn't an encrypted XLSX file
         // So, treat it as a regular HSSF XLS one
         if (password != null) {
@@ -116,53 +125,78 @@ public class WorkbookFactory {
         Biff8EncryptionKey.setCurrentUserPassword(null);
         return wb;
     }
-    
+
     /**
      * Creates a XSSFWorkbook from the given OOXML Package
-     * <p>Note that in order to properly release resources the 
-     *  Workbook should be closed after use.
+     *
+     * <p>Note that in order to properly release resources the
+     *  Workbook should be closed after use.</p>
+     *
+     *  @param pkg The {@link OPCPackage} opened for reading data.
+     *
+     *  @return The created Workbook
+     *
+     *  @throws IOException if an error occurs while reading the data
      */
     public static Workbook create(OPCPackage pkg) throws IOException {
         return new XSSFWorkbook(pkg);
     }
-    
+
     /**
      * Creates the appropriate HSSFWorkbook / XSSFWorkbook from
      *  the given InputStream.
+     *
      * <p>Your input stream MUST either support mark/reset, or
-     *  be wrapped as a {@link PushbackInputStream}! Note that 
-     *  using an {@link InputStream} has a higher memory footprint 
-     *  than using a {@link File}.</p> 
-     * <p>Note that in order to properly release resources the 
+     *  be wrapped as a {@link PushbackInputStream}! Note that
+     *  using an {@link InputStream} has a higher memory footprint
+     *  than using a {@link File}.</p>
+     *
+     * <p>Note that in order to properly release resources the
      *  Workbook should be closed after use. Note also that loading
      *  from an InputStream requires more memory than loading
-     *  from a File, so prefer {@link #create(File)} where possible. 
-     * @throws EncryptedDocumentException If the workbook given is password protected
+     *  from a File, so prefer {@link #create(File)} where possible.
+     *
+     *  @param inp The {@link InputStream} to read data from.
+     *
+     *  @return The created Workbook
+     *
+     *  @throws IOException if an error occurs while reading the data
+     *  @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link Workbook}
+     *  @throws EncryptedDocumentException If the workbook given is password protected
      */
     public static Workbook create(InputStream inp) throws IOException, InvalidFormatException, EncryptedDocumentException {
         return create(inp, null);
     }
-    
+
     /**
      * Creates the appropriate HSSFWorkbook / XSSFWorkbook from
      *  the given InputStream, which may be password protected.
      * <p>Your input stream MUST either support mark/reset, or
-     *  be wrapped as a {@link PushbackInputStream}! Note that 
-     *  using an {@link InputStream} has a higher memory footprint 
-     *  than using a {@link File}.</p> 
-     * <p>Note that in order to properly release resources the 
+     *  be wrapped as a {@link PushbackInputStream}! Note that
+     *  using an {@link InputStream} has a higher memory footprint
+     *  than using a {@link File}.</p>
+     *
+     * <p>Note that in order to properly release resources the
      *  Workbook should be closed after use. Note also that loading
      *  from an InputStream requires more memory than loading
-     *  from a File, so prefer {@link #create(File)} where possible.
-     * @throws EncryptedDocumentException If the wrong password is given for a protected file
-     * @throws EmptyFileException If an empty stream is given
+     *  from a File, so prefer {@link #create(File)} where possible.</p>
+     *
+     *  @param inp The {@link InputStream} to read data from.
+     *  @param password The password that should be used or null if no password is necessary.
+     *
+     *  @return The created Workbook
+     *
+     *  @throws IOException if an error occurs while reading the data
+     *  @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link Workbook}
+     *  @throws EncryptedDocumentException If the wrong password is given for a protected file
+     *  @throws EmptyFileException If an empty stream is given
      */
     public static Workbook create(InputStream inp, String password) throws IOException, InvalidFormatException, EncryptedDocumentException {
         // If clearly doesn't do mark/reset, wrap up
         if (! inp.markSupported()) {
             inp = new PushbackInputStream(inp, 8);
         }
-        
+
         // Ensure that there is at least some data there
         byte[] header8 = IOUtils.peekFirst8Bytes(inp);
 
@@ -176,51 +210,90 @@ public class WorkbookFactory {
         }
         throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");
     }
-    
+
     /**
      * Creates the appropriate HSSFWorkbook / XSSFWorkbook from
      *  the given File, which must exist and be readable.
-     * <p>Note that in order to properly release resources the 
+     * <p>Note that in order to properly release resources the
      *  Workbook should be closed after use.
-     * @throws EncryptedDocumentException If the workbook given is password protected
+     *
+     *  @param file The file to read data from.
+     *
+     *  @return The created Workbook
+     *
+     *  @throws IOException if an error occurs while reading the data
+     *  @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link Workbook}
+     *  @throws EncryptedDocumentException If the workbook given is password protected
      */
     public static Workbook create(File file) throws IOException, InvalidFormatException, EncryptedDocumentException {
         return create(file, null);
     }
+
     /**
      * Creates the appropriate HSSFWorkbook / XSSFWorkbook from
      *  the given File, which must exist and be readable, and
      *  may be password protected
-     * <p>Note that in order to properly release resources the 
+     * <p>Note that in order to properly release resources the
      *  Workbook should be closed after use.
-     * @throws EncryptedDocumentException If the wrong password is given for a protected file
-     * @throws EmptyFileException If an empty stream is given
+     *
+     *  @param file The file to read data from.
+     *  @param password The password that should be used or null if no password is necessary.
+     *
+     *  @return The created Workbook
+     *
+     *  @throws IOException if an error occurs while reading the data
+     *  @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link Workbook}
+     *  @throws EncryptedDocumentException If the wrong password is given for a protected file
+     *  @throws EmptyFileException If an empty stream is given
      */
     public static Workbook create(File file, String password) throws IOException, InvalidFormatException, EncryptedDocumentException {
+       return create(file, password, false);
+    }
+
+    /**
+     * Creates the appropriate HSSFWorkbook / XSSFWorkbook from
+     *  the given File, which must exist and be readable, and
+     *  may be password protected
+     * <p>Note that in order to properly release resources the
+     *  Workbook should be closed after use.
+     *
+     *  @param file The file to read data from.
+     *  @param password The password that should be used or null if no password is necessary.
+     *  @param readOnly If the Workbook should be opened in read-only mode to avoid writing back
+     *         changes when the document is closed.
+     *
+     *  @return The created Workbook
+     *
+     *  @throws IOException if an error occurs while reading the data
+     *  @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link Workbook}
+     *  @throws EncryptedDocumentException If the wrong password is given for a protected file
+     *  @throws EmptyFileException If an empty stream is given
+     */
+    public static Workbook create(File file, String password, boolean readOnly) throws IOException, InvalidFormatException, EncryptedDocumentException {
         if (! file.exists()) {
             throw new FileNotFoundException(file.toString());
         }
 
         try {
-            NPOIFSFileSystem fs = new NPOIFSFileSystem(file);
+            NPOIFSFileSystem fs = new NPOIFSFileSystem(file, readOnly);
             return create(fs, password);
         } catch(OfficeXmlFileException e) {
             // opening as .xls failed => try opening as .xlsx
-            OPCPackage pkg = OPCPackage.open(file);
+            OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
             try {
                 return new XSSFWorkbook(pkg);
             } catch (IOException ioe) {
                 // ensure that file handles are closed (use revert() to not re-write the file)
                 pkg.revert();
                 //pkg.close();
-                
+
                 // rethrow exception
                 throw ioe;
             } catch (IllegalArgumentException ioe) {
-                // ensure that file handles are closed (use revert() to not re-write the file) 
+                // ensure that file handles are closed (use revert() to not re-write the file)
                 pkg.revert();
                 //pkg.close();
-                
+
                 // rethrow exception
                 throw ioe;
             }
index 27d6d9ec1a126258c58d9b7fc16fb9eedc5f73ff..f3fcbb889e66dda4cbd01054acaa310908a8b7fa 100644 (file)
@@ -70,6 +70,22 @@ public final class TestWorkbookFactory extends TestCase {
         // TODO: this re-writes the sample-file?! wb.close();
     }
 
+    public void testCreateReadOnly() throws Exception {
+        Workbook wb;
+
+        // POIFS -> hssf
+        wb = WorkbookFactory.create(HSSFTestDataSamples.getSampleFile(xls), null, true);
+        assertNotNull(wb);
+        assertTrue(wb instanceof HSSFWorkbook);
+        wb.close();
+
+        // Package -> xssf
+        wb = WorkbookFactory.create(HSSFTestDataSamples.getSampleFile(xlsx), null, true);
+        assertNotNull(wb);
+        assertTrue(wb instanceof XSSFWorkbook);
+        wb.close();
+    }
+
     /**
      * Creates the appropriate kind of Workbook, but
      *  checking the mime magic at the start of the