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;
/**
* 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 {
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 {
} 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) {
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);
}
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;
}