@SuppressWarnings("unused")
@Internal
public class HSSFWorkbookFactory extends WorkbookFactory {
+
+ static {
+ WorkbookFactory.createHssfFromScratch = HSSFWorkbookFactory::createWorkbook;
+ WorkbookFactory.createHssfByNode = HSSFWorkbookFactory::createWorkbook;
+ }
+
/**
* Create a new empty Workbook
*
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.OldFileFormatException;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
import org.apache.poi.poifs.filesystem.FileMagic;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.IOUtils;
-public class SlideShowFactory {
+@SuppressWarnings("unchecked")
+public abstract class SlideShowFactory {
+
+ protected interface CreateSlideShow1<T> {
+ SlideShow<?, ?> apply(T t) throws IOException;
+ }
+
+ protected interface CreateSlideShow2<T, U> {
+ SlideShow<?, ?> apply(T t, U u) throws IOException;
+ }
+
+ // XMLSlideShow createSlideShow(InputStream stream)
+ protected static CreateSlideShow1<InputStream> createXslfByStream;
+
+ // XMLSlideShow createSlideShow(File file, boolean readOnly)
+ protected static CreateSlideShow2<File, Boolean> createXslfByFile;
+
+ // HSLFSlideShow createSlideShow(final POIFSFileSystem fs)
+ protected static CreateSlideShow1<POIFSFileSystem> createHslfByPoifs;
+
+ // HSLFSlideShow createSlideShow(final DirectoryNode root)
+ protected static CreateSlideShow1<DirectoryNode> createHslfByNode;
+
/**
* Creates a SlideShow from the given POIFSFileSystem.
*
InputStream stream = null;
try {
stream = DocumentFactoryHelper.getDecryptedStream(root, password);
-
- return createXSLFSlideShow(stream);
+ initXslf();
+ return (SlideShow<S, P>) createXslfByStream.apply(stream);
} finally {
IOUtils.closeQuietly(stream);
passwordSet = true;
}
try {
- return createHSLFSlideShow(root);
+ initHslf();
+ return (SlideShow<S, P>) createHslfByNode.apply(root);
} finally {
if (passwordSet) {
Biff8EncryptionKey.setCurrentUserPassword(null);
/**
* Creates the appropriate HSLFSlideShow / XMLSlideShow from
* the given InputStream, which may be password protected.
- *
+ *
* <p>Note that using an {@link InputStream} has a higher memory footprint
* than using a {@link File}.</p>
*
> SlideShow<S,P> create(InputStream inp, String password) throws IOException, EncryptedDocumentException {
InputStream is = FileMagic.prepareToCheckMagic(inp);
FileMagic fm = FileMagic.valueOf(is);
-
+
switch (fm) {
case OLE2:
POIFSFileSystem fs = new POIFSFileSystem(is);
return create(fs, password);
case OOXML:
- return createXSLFSlideShow(is);
+ initXslf();
+ return (SlideShow<S, P>) createXslfByStream.apply(is);
default:
throw new IOException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");
}
return create(fs, password);
} catch(OfficeXmlFileException e) {
IOUtils.closeQuietly(fs);
- return createXSLFSlideShow(file, readOnly);
+ initXslf();
+ return (SlideShow<S, P>) createXslfByFile.apply(file, readOnly);
} catch(RuntimeException e) {
IOUtils.closeQuietly(fs);
throw e;
}
}
-
- private static <
- S extends Shape<S,P>,
- P extends TextParagraph<S,P,? extends TextRun>
- > SlideShow<S,P> createHSLFSlideShow(Object... args) throws IOException, EncryptedDocumentException {
- return createSlideShow("org.apache.poi.hslf.usermodel.HSLFSlideShowFactory", args);
+
+ private static void initXslf() throws IOException {
+ if (createXslfByFile == null) {
+ initFactory("org.apache.poi.xslf.usermodel.XSLFSlideShowFactory", "poi-ooxml-*.jar");
+ }
}
-
- private static <
- S extends Shape<S,P>,
- P extends TextParagraph<S,P,? extends TextRun>
- > SlideShow<S,P> createXSLFSlideShow(Object... args) throws IOException, EncryptedDocumentException {
- return createSlideShow("org.apache.poi.xslf.usermodel.XSLFSlideShowFactory", args);
+
+ private static void initHslf() throws IOException {
+ if (createHslfByPoifs == null) {
+ initFactory("org.apache.poi.hslf.usermodel.HSLFSlideShowFactory", "poi-scratchpad-*.jar");
+ }
}
- private static <
- S extends Shape<S,P>,
- P extends TextParagraph<S,P,? extends TextRun>
- > SlideShow<S,P> createSlideShow(String factoryClass, Object[] args) throws IOException, EncryptedDocumentException {
- final Class<?> clazz;
+ private static void initFactory(String factoryClass, String jar) throws IOException {
try {
- clazz = SlideShowFactory.class.getClassLoader().loadClass(factoryClass);
+ Class.forName(factoryClass, true, SlideShowFactory.class.getClassLoader());
} catch (ClassNotFoundException e) {
- throw new IOException(factoryClass+" not found - check if poi-scratchpad.jar is on the classpath.");
- }
- try {
- Class<?>[] argsClz = new Class<?>[args.length];
- int i=0;
- for (Object o : args) {
- Class<?> c = o.getClass();
- if (Boolean.class.isAssignableFrom(c)) {
- c = boolean.class;
- } else if (InputStream.class.isAssignableFrom(c)) {
- c = InputStream.class;
- }
- argsClz[i++] = c;
- }
- Method m = clazz.getMethod("createSlideShow", argsClz);
- return (SlideShow<S,P>)m.invoke(null, args);
- } catch (InvocationTargetException e) {
- Throwable t = e.getCause();
- if (t instanceof IOException) {
- throw (IOException)t;
- } else if (t instanceof EncryptedDocumentException) {
- throw (EncryptedDocumentException)t;
- } else if (t instanceof OldFileFormatException) {
- throw (OldFileFormatException)t;
- } else if (t instanceof RuntimeException) {
- throw (RuntimeException)t;
- } else {
- throw new IOException(t);
- }
- } catch (Exception e) {
- throw new IOException(e);
+ throw new IOException(factoryClass+" not found - check if " + jar + " is on the classpath.");
}
}
}
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Arrays;
import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.OldFileFormatException;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
import org.apache.poi.poifs.filesystem.FileMagic;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Removal;
* (be it {@link HSSFWorkbook} or XSSFWorkbook),
* by auto-detecting from the supplied input.
*/
-public class WorkbookFactory {
+public abstract class WorkbookFactory {
+
+ protected interface CreateWorkbook0 {
+ Workbook apply() throws IOException;
+ }
+
+ protected interface CreateWorkbook1<T> {
+ Workbook apply(T t) throws IOException;
+ }
+
+ protected interface CreateWorkbook2<T, U> {
+ Workbook apply(T t, U u) throws IOException;
+ }
+
+ protected static CreateWorkbook0 createHssfFromScratch;
+ protected static CreateWorkbook1<DirectoryNode> createHssfByNode;
+
+ protected static CreateWorkbook0 createXssfFromScratch;
+ protected static CreateWorkbook1<InputStream> createXssfByStream;
+ protected static CreateWorkbook1<Object> createXssfByPackage;
+ protected static CreateWorkbook2<File,Boolean> createXssfByFile;
+
/**
* Create a new empty Workbook, either XSSF or HSSF depending
* on the parameter
*/
public static Workbook create(boolean xssf) throws IOException {
if(xssf) {
- return createXSSFWorkbook();
+ initXssf();
+ return createXssfFromScratch.apply();
} else {
- return createHSSFWorkbook();
+ initHssf();
+ return createHssfFromScratch.apply();
}
}
InputStream stream = null;
try {
stream = DocumentFactoryHelper.getDecryptedStream(root, password);
-
- return createXSSFWorkbook(stream);
+ initXssf();
+ return createXssfByStream.apply(stream);
} finally {
IOUtils.closeQuietly(stream);
passwordSet = true;
}
try {
- return createHSSFWorkbook(root);
+ initHssf();
+ return createHssfByNode.apply(root);
} finally {
if (passwordSet) {
Biff8EncryptionKey.setCurrentUserPassword(null);
@Deprecated
@Removal(version = "4.2.0")
public static Workbook create(Object pkg) throws IOException {
- return createXSSFWorkbook(pkg);
+ initXssf();
+ return createXssfByPackage.apply(pkg);
}
/**
POIFSFileSystem fs = new POIFSFileSystem(is);
return create(fs, password);
case OOXML:
- return createXSSFWorkbook(is);
+ initXssf();
+ return createXssfByStream.apply(is);
default:
throw new IOException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");
}
return create(fs, password);
} catch(OfficeXmlFileException e) {
IOUtils.closeQuietly(fs);
- return createXSSFWorkbook(file, readOnly);
+ initXssf();
+ return createXssfByFile.apply(file, readOnly);
} catch(RuntimeException e) {
IOUtils.closeQuietly(fs);
throw e;
}
}
- private static Workbook createHSSFWorkbook(Object... args) throws IOException, EncryptedDocumentException {
- return createWorkbook("org.apache.poi.hssf.usermodel.HSSFWorkbookFactory", args);
+ private static void initXssf() throws IOException {
+ if (createXssfFromScratch == null) {
+ initFactory("org.apache.poi.xssf.usermodel.XSSFWorkbookFactory", "poi-ooxml-*.jar");
+ }
}
- private static Workbook createXSSFWorkbook(Object... args) throws IOException, EncryptedDocumentException {
- return createWorkbook("org.apache.poi.xssf.usermodel.XSSFWorkbookFactory", args);
+ private static void initHssf() throws IOException {
+ if (createHssfFromScratch == null) {
+ // HSSF is part of the main jar, so this shouldn't fail ...
+ initFactory("org.apache.poi.hssf.usermodel.HSSFWorkbookFactory", "poi-*.jar");
+ }
}
- /**
- * Does the actual call to HSSF or XSSF to do the creation.
- * Uses reflection, so that this class can be in the Core non-OOXML
- * POI jar without errors / broken references to the OOXML / XSSF code.
- */
- private static Workbook createWorkbook(String factoryClass, Object[] args) throws IOException, EncryptedDocumentException {
+ private static void initFactory(String factoryClass, String jar) throws IOException {
try {
- Class<?> clazz = WorkbookFactory.class.getClassLoader().loadClass(factoryClass);
- Class<?>[] argsClz = new Class<?>[args.length];
- int i=0;
- for (Object o : args) {
- Class<?> c = o.getClass();
- if (Boolean.class.isAssignableFrom(c)) {
- c = boolean.class;
- } else if (InputStream.class.isAssignableFrom(c)) {
- c = InputStream.class;
- } else if (File.class.isAssignableFrom(c)) {
- c = File.class;
- }
- argsClz[i++] = c;
- }
- Method m = clazz.getMethod("createWorkbook", argsClz);
- return (Workbook)m.invoke(null, args);
- } catch (InvocationTargetException e) {
- Throwable t = e.getCause();
- if (t instanceof IOException) {
- throw (IOException)t;
- } else if (t instanceof EncryptedDocumentException) {
- throw (EncryptedDocumentException)t;
- } else if (t instanceof OldFileFormatException) {
- throw (OldFileFormatException)t;
- } else if (t instanceof RuntimeException) {
- throw (RuntimeException)t;
- } else {
- throw new IOException(t.getMessage(), t);
- }
- } catch (Exception e) {
- throw new IOException("While trying to invoke 'createWorkbook' on factory " + factoryClass +
- " and arguments " + Arrays.toString(args), e);
+ Class.forName(factoryClass, true, WorkbookFactory.class.getClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new IOException(factoryClass+" not found - check if " + jar + " is on the classpath.");
}
}
}
@Internal
public class XSLFSlideShowFactory extends SlideShowFactory {
+ static {
+ SlideShowFactory.createXslfByFile = XSLFSlideShowFactory::createSlideShow;
+ SlideShowFactory.createXslfByStream = XSLFSlideShowFactory::createSlideShow;
+ }
+
/**
* Creates a XMLSlideShow from the given OOXML Package.
* This is a convenience method to go along the create-methods of the super class.
* @return The created SlideShow
*
* @throws IOException if an error occurs while reading the data
- * @throws InvalidFormatException
*/
public static XMLSlideShow create(OPCPackage pkg) throws IOException {
try {
* @return The created SlideShow
*
* @throws IOException if an error occurs while reading the data
- * @throws InvalidFormatException
*/
public static XMLSlideShow createSlideShow(OPCPackage pkg) throws IOException {
try {
throw ioe;
}
}
-
+
/**
* Creates the XMLSlideShow from the given File, which must exist and be readable.
* <p>Note that in order to properly release resources theSlideShow should be closed after use.
*/
@SuppressWarnings("resource")
public static XMLSlideShow createSlideShow(File file, boolean readOnly)
- throws IOException, InvalidFormatException {
- OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
- return createSlideShow(pkg);
+ throws IOException {
+ try {
+ OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
+ return createSlideShow(pkg);
+ } catch (InvalidFormatException e) {
+ throw new IOException(e);
+ }
}
/**
* @return The created SlideShow
*
* @throws IOException if an error occurs while reading the data
- * @throws InvalidFormatException
*/
@SuppressWarnings("resource")
- public static XMLSlideShow createSlideShow(InputStream stream) throws IOException, InvalidFormatException {
- OPCPackage pkg = OPCPackage.open(stream);
- return createSlideShow(pkg);
+ public static XMLSlideShow createSlideShow(InputStream stream) throws IOException {
+ try {
+ OPCPackage pkg = OPCPackage.open(stream);
+ return createSlideShow(pkg);
+ } catch (InvalidFormatException e) {
+ throw new IOException(e);
+ }
}
}
import org.apache.poi.ss.usermodel.WorkbookFactory;
public class XSSFWorkbookFactory extends WorkbookFactory {
+
+ static {
+ WorkbookFactory.createXssfFromScratch = XSSFWorkbookFactory::createWorkbook;
+ WorkbookFactory.createXssfByStream = XSSFWorkbookFactory::createWorkbook;
+ WorkbookFactory.createXssfByPackage = o -> XSSFWorkbookFactory.createWorkbook((OPCPackage)o);
+ WorkbookFactory.createXssfByFile = XSSFWorkbookFactory::createWorkbook;
+ }
+
+
/**
* Create a new empty Workbook
*
* @throws EncryptedDocumentException If the wrong password is given for a protected file
*/
@SuppressWarnings("resource")
- public static XSSFWorkbook createWorkbook(File file, boolean readOnly)
- throws IOException, InvalidFormatException {
- OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
- return createWorkbook(pkg);
+ public static XSSFWorkbook createWorkbook(File file, boolean readOnly) throws IOException {
+ try {
+ OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
+ return createWorkbook(pkg);
+ } catch (InvalidFormatException e) {
+ throw new IOException(e);
+ }
}
/**
* @return The created Workbook
*
* @throws IOException if an error occurs while reading the data
- * @throws InvalidFormatException if the package is not valid.
*/
@SuppressWarnings("resource")
- public static XSSFWorkbook createWorkbook(InputStream stream) throws IOException, InvalidFormatException {
- OPCPackage pkg = OPCPackage.open(stream);
- return createWorkbook(pkg);
+ public static XSSFWorkbook createWorkbook(InputStream stream) throws IOException {
+ try {
+ OPCPackage pkg = OPCPackage.open(stream);
+ return createWorkbook(pkg);
+ } catch (InvalidFormatException e) {
+ throw new IOException(e);
+ }
}
}
private static final String[] xls_protected = new String[] {"password.xls", "password"};
private static final String[] xlsx_protected = new String[]{"protected_passtika.xlsx", "tika"};
private static final String txt = "SampleSS.txt";
-
+
private static final POILogger LOGGER = POILogFactory.getLogger(TestWorkbookFactory.class);
-
+
/**
* Closes the sample workbook read in from filename.
* Throws an exception if closing the workbook results in the file on disk getting modified.
assertArrayEquals(filename + " sample file was modified as a result of closing the workbook",
before, after);
}
-
+
/**
* bug 58779: Closing an XSSFWorkbook that was created with WorkbookFactory modifies the file
* FIXME: replace this method with wb.close() when bug 58779 is resolved.
// expected here
}
}
-
+
/**
* Check that a helpful exception is given on an empty input stream
*/
- @Test
+ @Test(expected = EmptyFileException.class)
public void testEmptyInputStream() throws Exception {
InputStream emptyStream = new ByteArrayInputStream(new byte[0]);
- try {
- WorkbookFactory.create(emptyStream);
- fail("Shouldn't be able to create for an empty stream");
- } catch (final EmptyFileException expected) {}
+ WorkbookFactory.create(emptyStream);
}
-
+
/**
* Check that a helpful exception is given on an empty file
*/
- @Test
+ @Test(expected = EmptyFileException.class)
public void testEmptyFile() throws Exception {
File emptyFile = TempFile.createTempFile("empty", ".poi");
try {
WorkbookFactory.create(emptyFile);
fail("Shouldn't be able to create for an empty file");
- } catch (final EmptyFileException expected) {
- // expected here
+ } finally {
+ assertTrue(emptyFile.delete());
}
-
- assertTrue(emptyFile.delete());
}
/**
* Check that a helpful exception is raised on a non-existing file
*/
- @Test
+ @Test(expected = FileNotFoundException.class)
public void testNonExistingFile() throws Exception {
File nonExistingFile = new File("notExistingFile");
assertFalse(nonExistingFile.exists());
-
- try {
- WorkbookFactory.create(nonExistingFile, "password", true);
- fail("Should not be able to create for a non-existing file");
- } catch (final FileNotFoundException e) {
- // expected
- }
+ WorkbookFactory.create(nonExistingFile, "password", true);
}
/**
* See Bugzilla bug #62831 - #WorkbookFactory.create(File) needs
* to work for sub-classes of File too, eg JFileChooser
*/
- @Test
+ @Test(expected = ClassCastException.class)
public void testFileSubclass() throws Exception {
File normalXLS = HSSFTestDataSamples.getSampleFile(xls);
File normalXLSX = HSSFTestDataSamples.getSampleFile(xlsx);
// check what happens if the file is passed as "Object"
- try {
- //noinspection deprecation
- WorkbookFactory.create((Object)altXLSX);
- fail("Will throw an exception");
- } catch(IOException e) {
- // expected here because create() in this case expects an object of type "OPCPackage"
- }
+ //noinspection deprecation
+ WorkbookFactory.create((Object)altXLSX);
+ // expected a ClassCastException here because create() in this case expects an object of type "OPCPackage"
}
-
+
private static class TestFile extends File {
public TestFile(String file) {
super(file);
closeOrRevert(wb);
}
- @Test
- public void testInvalidFormatException() {
+ @Test(expected = IOException.class)
+ public void testInvalidFormatException() throws IOException {
String filename = "OPCCompliance_DerivedPartNameFAIL.docx";
- try {
- WorkbookFactory.create(POIDataSamples.getOpenXML4JInstance().openResourceAsStream(filename));
- fail("Expecting an Exception for this document");
- } catch (IOException e) {
- // expected here
- }
+ WorkbookFactory.create(POIDataSamples.getOpenXML4JInstance().openResourceAsStream(filename));
}
}
@SuppressWarnings("unused")
@Internal
public class HSLFSlideShowFactory extends SlideShowFactory {
+
+ static {
+ SlideShowFactory.createHslfByNode = HSLFSlideShowFactory::createSlideShow;
+ SlideShowFactory.createHslfByPoifs = HSLFSlideShowFactory::createSlideShow;
+ }
+
/**
* Creates a HSLFSlideShow from the given {@link POIFSFileSystem}<p>
* Note that in order to properly release resources the