]> source.dussan.org Git - poi.git/commitdiff
#64411 - Provide JigSaw modules
authorAndreas Beeker <kiwiwings@apache.org>
Fri, 14 Aug 2020 19:08:42 +0000 (19:08 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Fri, 14 Aug 2020 19:08:42 +0000 (19:08 +0000)
- use service locator for SlideShowFactory

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

22 files changed:
src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java
src/java/org/apache/poi/sl/usermodel/SlideShowProvider.java [new file with mode: 0644]
src/java/org/apache/poi/ss/usermodel/WorkbookFactory.java
src/multimodule/ooxml/java9/module-info.class
src/multimodule/ooxml/java9/module-info.java
src/multimodule/ooxml/test9/module-info.class
src/multimodule/ooxml/test9/module-info.java
src/multimodule/poi/java9/module-info.class
src/multimodule/poi/java9/module-info.java
src/multimodule/poi/test9/module-info.class
src/multimodule/poi/test9/module-info.java
src/multimodule/scratchpad/java9/module-info.class
src/multimodule/scratchpad/java9/module-info.java
src/multimodule/scratchpad/test9/module-info.class
src/multimodule/scratchpad/test9/module-info.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideShowFactory.java
src/resources/ooxml/META-INF/services/org.apache.poi.sl.usermodel.SlideShowProvider [new file with mode: 0644]
src/resources/scratchpad/META-INF/services/org.apache.poi.sl.usermodel.SlideShowProvider [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/extractor/ole2/OLE2ScratchpadExtractorFactory.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowFactory.java
src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java
src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShowFactory.java

index 84d98e70acdf94c9b572c04e0f4fb51f35316289..1424a70608bdb03e5e54ab37b30b17a7f1a401af 100644 (file)
 ==================================================================== */
 package org.apache.poi.sl.usermodel;
 
+import static org.apache.poi.poifs.crypt.EncryptionInfo.ENCRYPTION_INFO_ENTRY;
+
+import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ServiceLoader;
 
+import org.apache.poi.EmptyFileException;
 import org.apache.poi.EncryptedDocumentException;
-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.OfficeXmlFileException;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.util.IOUtils;
 
-@SuppressWarnings("unchecked")
-public abstract class SlideShowFactory {
+public final class SlideShowFactory {
 
-    protected interface CreateSlideShow1<T> {
-        SlideShow<?, ?> apply(T t) throws IOException;
+    private static class Singleton {
+        private static final SlideShowFactory INSTANCE = new SlideShowFactory();
     }
 
-    protected interface CreateSlideShow2<T, U> {
-        SlideShow<?, ?> apply(T t, U u) throws IOException;
+    private interface ProviderMethod {
+        SlideShow<?,?> create(SlideShowProvider<?,?> prov) throws IOException;
     }
 
-    // XMLSlideShow createSlideShow(InputStream stream)
-    protected static CreateSlideShow1<InputStream> createXslfByStream;
-
-    // XMLSlideShow createSlideShow(File file, boolean readOnly)
-    protected static CreateSlideShow2<File, Boolean> createXslfByFile;
+    private final List<SlideShowProvider<?,?>> provider = new ArrayList<>();
 
-    // HSLFSlideShow createSlideShow(final POIFSFileSystem fs)
-    protected static CreateSlideShow1<POIFSFileSystem> createHslfByPoifs;
+    private SlideShowFactory() {
+        ServiceLoader.load(SlideShowProvider.class).forEach(provider::add);
+    }
 
-    // HSLFSlideShow createSlideShow(final DirectoryNode root)
-    protected static CreateSlideShow1<DirectoryNode> createHslfByNode;
+    /**
+     * Create a new empty SlideShow, either XSLF or HSLF depending
+     * on the parameter
+     *
+     * @param XSLF If an XSLFSlideShow or a HSLFSlideShow should be created
+     *
+     * @return The created SlideShow
+     *
+     * @throws IOException if an error occurs while creating the objects
+     */
+    public static SlideShow<?,?> create(boolean XSLF) throws IOException {
+        return wp(XSLF ? FileMagic.OOXML : FileMagic.OLE2, SlideShowProvider::create);
+    }
 
     /**
-     * Creates a SlideShow from the given POIFSFileSystem.
+     * Creates a HSLFSlideShow from the given POIFSFileSystem<p>
+     *
+     * Note that in order to properly release resources the
+     * SlideShow should be closed after use.
      *
      * @param fs The {@link POIFSFileSystem} to read the document from
      *
@@ -63,31 +76,26 @@ public abstract class SlideShowFactory {
      *
      * @throws IOException if an error occurs while reading the data
      */
-    public static <
-        S extends Shape<S,P>,
-        P extends TextParagraph<S,P,? extends TextRun>
-    > SlideShow<S,P> create(POIFSFileSystem fs) throws IOException {
+    public static SlideShow<?,?> create(POIFSFileSystem fs) throws IOException {
         return create(fs, null);
     }
 
     /**
      * Creates a SlideShow from the given POIFSFileSystem, which may
-     * be password protected
+     *  be password protected
      *
-     * @param fs The {@link POIFSFileSystem} to read the document from
-     * @param password The password that should be used or null if no password is necessary.
+     *  @param fs The {@link POIFSFileSystem} to read the document from
+     *  @param password The password that should be used or null if no password is necessary.
      *
-     * @return The created SlideShow
+     *  @return The created SlideShow
      *
-     * @throws IOException if an error occurs while reading the data
+     *  @throws IOException if an error occurs while reading the data
      */
-    public static <
-        S extends Shape<S,P>,
-        P extends TextParagraph<S,P,? extends TextRun>
-    > SlideShow<S,P> create(final POIFSFileSystem fs, String password) throws IOException {
+    private static SlideShow<?,?> create(final POIFSFileSystem fs, String password) throws IOException {
         return create(fs.getRoot(), password);
     }
 
+
     /**
      * Creates a SlideShow from the given DirectoryNode.
      *
@@ -97,10 +105,7 @@ public abstract class SlideShowFactory {
      *
      * @throws IOException if an error occurs while reading the data
      */
-    public static <
-        S extends Shape<S,P>,
-        P extends TextParagraph<S,P,? extends TextRun>
-    > SlideShow<S,P> create(final DirectoryNode root) throws IOException {
+    public static SlideShow<?,?> create(final DirectoryNode root) throws IOException {
         return create(root, null);
     }
 
@@ -116,48 +121,22 @@ public abstract class SlideShowFactory {
      *
      * @throws IOException if an error occurs while reading the data
      */
-    public static <
-        S extends Shape<S,P>,
-        P extends TextParagraph<S,P,? extends TextRun>
-    > SlideShow<S,P> create(final DirectoryNode root, String password) throws IOException {
+    public static SlideShow<?,?> create(final DirectoryNode root, String password) throws IOException {
         // Encrypted OOXML files go inside OLE2 containers, is this one?
         if (root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) {
-            InputStream stream = null;
-            try {
-                stream = DocumentFactoryHelper.getDecryptedStream(root, password);
-                initXslf();
-                return (SlideShow<S, P>) createXslfByStream.apply(stream);
-            } finally {
-                IOUtils.closeQuietly(stream);
-
-                // as we processed the full stream already, we can close the filesystem here
-                // otherwise file handles are leaked
-                root.getFileSystem().close();
-            }
-        }
-
-        // If we get here, it isn't an encrypted PPTX file
-        // So, treat it as a regular HSLF PPT one
-        boolean passwordSet = false;
-        if (password != null) {
-            Biff8EncryptionKey.setCurrentUserPassword(password);
-            passwordSet = true;
-        }
-        try {
-            initHslf();
-            return (SlideShow<S, P>) createHslfByNode.apply(root);
-        } finally {
-            if (passwordSet) {
-                Biff8EncryptionKey.setCurrentUserPassword(null);
-            }
+            return wp(FileMagic.OOXML, w -> w.create(root, password));
+        } else {
+            return wp(FileMagic.OLE2, w ->  w.create(root, password));
         }
     }
 
     /**
-     * Creates the appropriate HSLFSlideShow / XMLSlideShow from
+     * Creates the appropriate HSLFSlideShow / XSLFSlideShow from
      *  the given InputStream.
      *
-     * <p>Note that using an {@link InputStream} has a higher memory footprint
+     * <p>Your input stream MUST either support mark/reset, or
+     *  be wrapped as a {@link BufferedInputStream}!
+     *  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
@@ -170,20 +149,19 @@ public abstract class SlideShowFactory {
      *  @return The created SlideShow
      *
      *  @throws IOException if an error occurs while reading the data
-     *  @throws EncryptedDocumentException If the SlideShow given is password protected
+     *  @throws EncryptedDocumentException If the SlideShow<?,?> given is password protected
      */
-    public static <
-        S extends Shape<S,P>,
-        P extends TextParagraph<S,P,? extends TextRun>
-    > SlideShow<S,P> create(InputStream inp) throws IOException, EncryptedDocumentException {
+    public static SlideShow<?,?> create(InputStream inp) throws IOException, EncryptedDocumentException {
         return create(inp, null);
     }
 
     /**
-     * Creates the appropriate HSLFSlideShow / XMLSlideShow from
+     * Creates the appropriate HSLFSlideShow / XSLFSlideShow from
      *  the given InputStream, which may be password protected.
      *
-     * <p>Note that using an {@link InputStream} has a higher memory footprint
+     * <p>Your input stream MUST either support mark/reset, or
+     *  be wrapped as a {@link BufferedInputStream}!
+     *  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
@@ -199,27 +177,32 @@ public abstract class SlideShowFactory {
      *  @throws IOException if an error occurs while reading the data
      *  @throws EncryptedDocumentException If the wrong password is given for a protected file
      */
-    public static <
-        S extends Shape<S,P>,
-        P extends TextParagraph<S,P,? extends TextRun>
-    > SlideShow<S,P> create(InputStream inp, String password) throws IOException, EncryptedDocumentException {
+    public static SlideShow<?,?> 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:
-            initXslf();
-            return (SlideShow<S, P>) createXslfByStream.apply(is);
-        default:
-            throw new IOException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");
+        byte[] emptyFileCheck = new byte[1];
+        is.mark(emptyFileCheck.length);
+        if (is.read(emptyFileCheck) < emptyFileCheck.length) {
+            throw new EmptyFileException();
+        }
+        is.reset();
+
+        final FileMagic fm = FileMagic.valueOf(is);
+        if (FileMagic.OOXML == fm) {
+            return wp(fm, w -> w.create(is));
+        }
+
+        if (FileMagic.OLE2 != fm) {
+            throw new IOException("Can't open SlideShow - unsupported file type: "+fm);
         }
+
+        POIFSFileSystem poifs = new POIFSFileSystem(is);
+        boolean isOOXML = poifs.getRoot().hasEntry(ENCRYPTION_INFO_ENTRY);
+
+        return wp(isOOXML ? FileMagic.OOXML : fm, w -> w.create(poifs.getRoot(), password));
     }
 
     /**
-     * Creates the appropriate HSLFSlideShow / XMLSlideShow from
+     * Creates the appropriate HSLFSlideShow / XSLFSlideShow from
      *  the given File, which must exist and be readable.
      * <p>Note that in order to properly release resources the
      *  SlideShow should be closed after use.
@@ -231,15 +214,12 @@ public abstract class SlideShowFactory {
      *  @throws IOException if an error occurs while reading the data
      *  @throws EncryptedDocumentException If the SlideShow given is password protected
      */
-    public static <
-        S extends Shape<S,P>,
-        P extends TextParagraph<S,P,? extends TextRun>
-    > SlideShow<S,P> create(File file) throws IOException, EncryptedDocumentException {
+    public static SlideShow<?,?> create(File file) throws IOException, EncryptedDocumentException {
         return create(file, null);
     }
 
     /**
-     * Creates the appropriate HSLFSlideShow / XMLSlideShow from
+     * Creates the appropriate HSLFSlideShow / XSLFSlideShow 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
@@ -253,15 +233,12 @@ public abstract class SlideShowFactory {
      *  @throws IOException if an error occurs while reading the data
      *  @throws EncryptedDocumentException If the wrong password is given for a protected file
      */
-    public static <
-        S extends Shape<S,P>,
-        P extends TextParagraph<S,P,? extends TextRun>
-    > SlideShow<S,P> create(File file, String password) throws IOException, EncryptedDocumentException {
+    public static SlideShow<?,?> create(File file, String password) throws IOException, EncryptedDocumentException {
         return create(file, password, false);
     }
 
     /**
-     * Creates the appropriate HSLFSlideShow / XMLSlideShow from
+     * Creates the appropriate HSLFSlideShow / XSLFSlideShow 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
@@ -277,45 +254,39 @@ public abstract class SlideShowFactory {
      *  @throws IOException if an error occurs while reading the data
      *  @throws EncryptedDocumentException If the wrong password is given for a protected file
      */
-    public static <
-        S extends Shape<S,P>,
-        P extends TextParagraph<S,P,? extends TextRun>
-    > SlideShow<S,P> create(File file, String password, boolean readOnly) throws IOException, EncryptedDocumentException {
+    public static SlideShow<?,?> create(File file, String password, boolean readOnly) throws IOException, EncryptedDocumentException {
         if (!file.exists()) {
             throw new FileNotFoundException(file.toString());
         }
 
-        POIFSFileSystem fs = null;
-        try {
-            fs = new POIFSFileSystem(file, readOnly);
-            return create(fs, password);
-        } catch(OfficeXmlFileException e) {
-            IOUtils.closeQuietly(fs);
-            initXslf();
-            return (SlideShow<S, P>) createXslfByFile.apply(file, readOnly);
-        } catch(RuntimeException e) {
-            IOUtils.closeQuietly(fs);
-            throw e;
+        if (file.length() == 0) {
+            throw new EmptyFileException();
         }
-    }
 
-    private static void initXslf() throws IOException {
-        if (createXslfByFile == null) {
-            initFactory("org.apache.poi.xslf.usermodel.XSLFSlideShowFactory", "poi-ooxml-*.jar");
+        FileMagic fm = FileMagic.valueOf(file);
+        if (fm == FileMagic.OOXML) {
+            return wp(fm, w -> w.create(file, password, readOnly));
+        } else if (fm == FileMagic.OLE2) {
+            final boolean ooxmlEnc;
+            try (POIFSFileSystem fs = new POIFSFileSystem(file, true)) {
+                ooxmlEnc = fs.getRoot().hasEntry(Decryptor.DEFAULT_POIFS_ENTRY);
+            }
+            return wp(ooxmlEnc ? FileMagic.OOXML : fm, w -> w.create(file, password, readOnly));
         }
-    }
 
-    private static void initHslf() throws IOException {
-        if (createHslfByPoifs == null) {
-            initFactory("org.apache.poi.hslf.usermodel.HSLFSlideShowFactory", "poi-scratchpad-*.jar");
-        }
+        return null;
     }
 
-    private static void initFactory(String factoryClass, String jar) throws IOException {
-        try {
-            Class.forName(factoryClass, true, SlideShowFactory.class.getClassLoader());
-        } catch (ClassNotFoundException e) {
-            throw new IOException(factoryClass+" not found - check if " + jar + " is on the classpath.");
+
+
+    private static SlideShow<?,?> wp(FileMagic fm, SlideShowFactory.ProviderMethod fun) throws IOException {
+
+        for (SlideShowProvider<?,?> prov : SlideShowFactory.Singleton.INSTANCE.provider) {
+            if (prov.accepts(fm)) {
+                return fun.create(prov);
+            }
         }
+        throw new IOException("Your InputStream was neither an OLE2 stream, nor an OOXML stream " +
+                                      "or you haven't provide the poi-ooxml*.jar in the classpath/modulepath - FileMagic: "+fm);
     }
 }
diff --git a/src/java/org/apache/poi/sl/usermodel/SlideShowProvider.java b/src/java/org/apache/poi/sl/usermodel/SlideShowProvider.java
new file mode 100644 (file)
index 0000000..3dbde3c
--- /dev/null
@@ -0,0 +1,42 @@
+/* ====================================================================
+   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.sl.usermodel;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.poifs.filesystem.FileMagic;
+
+public interface SlideShowProvider<
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+> {
+    boolean accepts(FileMagic fm);
+
+    SlideShow<S,P> create();
+
+    SlideShow<S,P> create(InputStream inp) throws IOException;
+
+    SlideShow<S,P> create(InputStream inp, String password) throws IOException;
+
+    SlideShow<S,P> create(DirectoryNode root, String password) throws IOException;
+
+    SlideShow<S,P> create(File file, String password, boolean readOnly) throws IOException;
+}
index 25f5cde753ef792deef149cec4ce608b6a2351fb..d9504fe63a30a84bce5ae7b924c23ae5dcb5e172 100644 (file)
@@ -274,7 +274,7 @@ public final class WorkbookFactory {
         if (fm == FileMagic.OOXML) {
             return wp(fm, w -> w.create(file, password, readOnly));
         } else if (fm == FileMagic.OLE2) {
-            boolean ooxmlEnc = false;
+            final boolean ooxmlEnc;
             try (POIFSFileSystem fs = new POIFSFileSystem(file, true)) {
                 ooxmlEnc = fs.getRoot().hasEntry(Decryptor.DEFAULT_POIFS_ENTRY);
             }
index 0895d4b496877476aabecd9fc83cf487727451ee..517b8bbe2c795ea4aaa15af69477f66ea30d1e4d 100644 (file)
Binary files a/src/multimodule/ooxml/java9/module-info.class and b/src/multimodule/ooxml/java9/module-info.class differ
index 876e6a3b1d84707c9f693de1d5d78a98174d3f4c..66928ffa24e605ba66bd2086168cd35e22b8fd3a 100644 (file)
@@ -28,8 +28,9 @@ module org.apache.poi.ooxml {
     requires java.desktop;
     requires java.security.jgss;
 
-    provides org.apache.poi.ss.usermodel.WorkbookProvider with org.apache.poi.xssf.usermodel.XSSFWorkbookFactory;
     provides org.apache.poi.extractor.ExtractorProvider with org.apache.poi.ooxml.extractor.POIXMLExtractorFactory;
+    provides org.apache.poi.ss.usermodel.WorkbookProvider with org.apache.poi.xssf.usermodel.XSSFWorkbookFactory;
+    provides org.apache.poi.sl.usermodel.SlideShowProvider with org.apache.poi.xslf.usermodel.XSLFSlideShowFactory;
 
     exports org.apache.poi.xwpf.extractor;
     exports org.apache.poi.xwpf.usermodel;
@@ -79,7 +80,7 @@ module org.apache.poi.ooxml {
     opens org.apache.poi.openxml4j.opc to org.apache.poi.poi;
 
 
-    /* optional dependencies for xml signatures - you need to add a require entry your module-info
+    /* optional dependencies for xml signatures - you need to add a require entry to your module-info
      * or add them via the --add-modules JVM argument */
     requires java.xml.crypto;
     requires static org.apache.santuario.xmlsec;
index 7777b5f6815c43d46b442fd5fa3a192b4595e44e..be87166834c83e09dd5b6d7b7db577c119f6e059 100644 (file)
Binary files a/src/multimodule/ooxml/test9/module-info.class and b/src/multimodule/ooxml/test9/module-info.class differ
index bd8a23a7250b007fdc8d6b86afc9dc70beb2ac17..b41ae2b9b631409e96043114d42b7c540efa058c 100644 (file)
@@ -28,8 +28,9 @@ module org.apache.poi.ooxml {
     requires java.desktop;
     requires java.security.jgss;
 
-    provides org.apache.poi.ss.usermodel.WorkbookProvider with org.apache.poi.xssf.usermodel.XSSFWorkbookFactory;
     provides org.apache.poi.extractor.ExtractorProvider with org.apache.poi.ooxml.extractor.POIXMLExtractorFactory;
+    provides org.apache.poi.ss.usermodel.WorkbookProvider with org.apache.poi.xssf.usermodel.XSSFWorkbookFactory;
+    provides org.apache.poi.sl.usermodel.SlideShowProvider with org.apache.poi.xslf.usermodel.XSLFSlideShowFactory;
 
     exports org.apache.poi.xwpf.extractor;
     exports org.apache.poi.xwpf.usermodel;
index ba2f2330ed860c9fc5c11cc23c4641012eb8e300..ab0e08c35869c28e8b35ad17b2b274bf76026c93 100644 (file)
Binary files a/src/multimodule/poi/java9/module-info.class and b/src/multimodule/poi/java9/module-info.class differ
index 2995a218640ac01a6211c164392fa0ea1c96bd76..ea3f394035aa0f9e0d55e721ab265fba20a8ff15 100644 (file)
@@ -27,8 +27,9 @@ module org.apache.poi.poi {
     /* needed for CleanerUtil */
     requires jdk.unsupported;
 
-    uses org.apache.poi.ss.usermodel.WorkbookProvider;
     uses org.apache.poi.extractor.ExtractorProvider;
+    uses org.apache.poi.ss.usermodel.WorkbookProvider;
+    uses org.apache.poi.sl.usermodel.SlideShowProvider;
 
 
     provides org.apache.poi.ss.usermodel.WorkbookProvider with org.apache.poi.hssf.usermodel.HSSFWorkbookFactory;
index 9010295aa09fe706e8109f234dfa5f2a9527416f..2b43c43fa8d263524cb541d0084236d6e298d98f 100644 (file)
Binary files a/src/multimodule/poi/test9/module-info.class and b/src/multimodule/poi/test9/module-info.class differ
index add80713097cc0c677fdaabc61602815ed623a13..9e5bc0a110855c4d05c94006ab7120f30fc99d21 100644 (file)
@@ -27,8 +27,9 @@ module org.apache.poi.poi {
     /* needed for CleanerUtil */
     requires jdk.unsupported;
 
-    uses org.apache.poi.ss.usermodel.WorkbookProvider;
     uses org.apache.poi.extractor.ExtractorProvider;
+    uses org.apache.poi.ss.usermodel.WorkbookProvider;
+    uses org.apache.poi.sl.usermodel.SlideShowProvider;
 
     provides org.apache.poi.ss.usermodel.WorkbookProvider with org.apache.poi.hssf.usermodel.HSSFWorkbookFactory;
     provides org.apache.poi.extractor.ExtractorProvider with org.apache.poi.extractor.MainExtractorFactory;
index 5e04b3dec90cab4a6618303c47b550af9a8909c6..8697888d28aa9f0160a173630b34b8024aae7e40 100644 (file)
Binary files a/src/multimodule/scratchpad/java9/module-info.class and b/src/multimodule/scratchpad/java9/module-info.class differ
index 717730fdd491651bfa9dea04eaeac5467dbca20e..b936858c707173be68f9ebb7dbd68a213f903c97 100644 (file)
@@ -21,6 +21,7 @@ module org.apache.poi.scratchpad {
     requires commons.math3;
 
     provides org.apache.poi.extractor.ExtractorProvider with org.apache.poi.extractor.ole2.OLE2ScratchpadExtractorFactory;
+    provides org.apache.poi.sl.usermodel.SlideShowProvider with org.apache.poi.hslf.usermodel.HSLFSlideShowFactory;
 
     exports org.apache.poi.hmef;
     exports org.apache.poi.hmef.dev;
index 489d1d1ab92275167d33a3cb01f534a3e45de336..4ee1e56a657302645cc8efca30f6ca4d0a5e5f84 100644 (file)
Binary files a/src/multimodule/scratchpad/test9/module-info.class and b/src/multimodule/scratchpad/test9/module-info.class differ
index db69fd4e8fcc901cb13253a6edcaa283a4bf19f7..cb0691b9a1267a079a649ce421942707ea21e0eb 100644 (file)
@@ -21,6 +21,7 @@ module org.apache.poi.scratchpad {
     requires commons.math3;
 
     provides org.apache.poi.extractor.ExtractorProvider with org.apache.poi.extractor.ole2.OLE2ScratchpadExtractorFactory;
+    provides org.apache.poi.sl.usermodel.SlideShowProvider with org.apache.poi.hslf.usermodel.HSLFSlideShowFactory;
 
     exports org.apache.poi.hmef;
     exports org.apache.poi.hmef.dev;
index 548cdc7a08809d152fd35ca553f8cf0880e0782c..929b000bbb0051edeb6b45c6fa6b1335b1f78259 100644 (file)
@@ -25,40 +25,81 @@ import org.apache.poi.EncryptedDocumentException;
 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.sl.usermodel.SlideShowFactory;
+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.sl.usermodel.SlideShowProvider;
 import org.apache.poi.util.Internal;
 
 @Internal
-public class XSLFSlideShowFactory extends SlideShowFactory {
+public class XSLFSlideShowFactory implements SlideShowProvider<XSLFShape,XSLFTextParagraph> {
 
-    static {
-        SlideShowFactory.createXslfByFile = XSLFSlideShowFactory::createSlideShow;
-        SlideShowFactory.createXslfByStream = XSLFSlideShowFactory::createSlideShow;
+    @Override
+    public boolean accepts(FileMagic fm) {
+        return fm == FileMagic.OOXML;
     }
 
     /**
-     * Creates a XMLSlideShow from the given OOXML Package.
-     * This is a convenience method to go along the create-methods of the super class.
+     * Create a new empty SlideShow
+     *
+     * @return The created SlideShow
+     */
+    @Override
+    public XMLSlideShow create() {
+        return new XMLSlideShow();
+    }
+
+    @Override
+    public XMLSlideShow create(DirectoryNode root, String password) throws IOException {
+        try (InputStream stream = DocumentFactoryHelper.getDecryptedStream(root, password)) {
+            return create(stream);
+        } finally {
+            // as we processed the full stream already, we can close the filesystem here
+            // otherwise file handles are leaked
+            root.getFileSystem().close();
+        }
+    }
+
+    @Override
+    public XMLSlideShow create(InputStream inp, String password) throws IOException {
+        InputStream bufInp = FileMagic.prepareToCheckMagic(inp);
+        FileMagic fm = FileMagic.valueOf(bufInp);
+
+        if (fm == FileMagic.OLE2) {
+            try (POIFSFileSystem poifs = new POIFSFileSystem(bufInp);
+                 InputStream stream = DocumentFactoryHelper.getDecryptedStream(poifs.getRoot(), password)) {
+                return create(stream);
+            }
+        }
+
+        if (fm == FileMagic.OOXML) {
+            return create(bufInp);
+        }
+
+        return null;
+    }
+
+    /**
+     * Creates a XMLSlideShow from the given InputStream
      *
      * <p>Note that in order to properly release resources the
-     *  SlideShow should be closed after use.</p>
+     * SlideShow should be closed after use.</p>
      *
-     *  @param pkg The {@link OPCPackage} opened for reading data.
+     * @param stream The {@link InputStream} to read data from.
      *
-     *  @return The created SlideShow
+     * @return The created SlideShow
      *
-     *  @throws IOException if an error occurs while reading the data
+     * @throws IOException if an error occurs while reading the data
      */
-    public static XMLSlideShow create(OPCPackage pkg) throws IOException {
+    @SuppressWarnings("resource")
+    @Override
+    public XMLSlideShow create(InputStream stream) throws IOException {
         try {
-            return new XMLSlideShow(pkg);
-        } catch (IllegalArgumentException ioe) {
-            // ensure that file handles are closed (use revert() to not re-write the file)
-            pkg.revert();
-            //pkg.close();
-
-            // rethrow exception
-            throw ioe;
+            OPCPackage pkg = OPCPackage.open(stream);
+            return createSlideShow(pkg);
+        } catch (InvalidFormatException e) {
+            throw new IOException(e);
         }
     }
 
@@ -77,7 +118,7 @@ public class XSLFSlideShowFactory extends SlideShowFactory {
     public static XMLSlideShow createSlideShow(OPCPackage pkg) throws IOException {
         try {
             return new XMLSlideShow(pkg);
-        } catch (IllegalArgumentException ioe) {
+        } catch (RuntimeException ioe) {
             // ensure that file handles are closed (use revert() to not re-write the file)
             pkg.revert();
             //pkg.close();
@@ -89,7 +130,7 @@ public class XSLFSlideShowFactory extends SlideShowFactory {
 
     /**
      * 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.
+     * <p>Note that in order to properly release resources the SlideShow should be closed after use.
      *
      *  @param file The file to read data from.
      *  @param readOnly If the SlideShow should be opened in read-only mode to avoid writing back
@@ -101,36 +142,21 @@ public class XSLFSlideShowFactory extends SlideShowFactory {
      *  @throws EncryptedDocumentException If the wrong password is given for a protected file
      */
     @SuppressWarnings("resource")
-    public static XMLSlideShow createSlideShow(File file, boolean readOnly)
-    throws IOException {
-        try {
-            OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
-            return createSlideShow(pkg);
-        } catch (InvalidFormatException e) {
-            throw new IOException(e);
+    public XMLSlideShow create(File file, String password, boolean readOnly) throws IOException {
+        FileMagic fm = FileMagic.valueOf(file);
+
+        if (fm == FileMagic.OLE2) {
+            try (POIFSFileSystem poifs = new POIFSFileSystem(file, true);
+                 InputStream stream = DocumentFactoryHelper.getDecryptedStream(poifs.getRoot(), password)) {
+                return create(stream);
+            }
         }
-    }
 
-    /**
-     * Creates a XMLSlideShow from the given InputStream
-     *
-     * <p>Note that in order to properly release resources the
-     * SlideShow should be closed after use.</p>
-     *
-     * @param stream The {@link InputStream} to read data from.
-     *
-     * @return The created SlideShow
-     *
-     * @throws IOException if an error occurs while reading the data
-     */
-    @SuppressWarnings("resource")
-    public static XMLSlideShow createSlideShow(InputStream stream) throws IOException {
         try {
-            OPCPackage pkg = OPCPackage.open(stream);
+            OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
             return createSlideShow(pkg);
         } catch (InvalidFormatException e) {
             throw new IOException(e);
         }
     }
-
 }
diff --git a/src/resources/ooxml/META-INF/services/org.apache.poi.sl.usermodel.SlideShowProvider b/src/resources/ooxml/META-INF/services/org.apache.poi.sl.usermodel.SlideShowProvider
new file mode 100644 (file)
index 0000000..f4251ab
--- /dev/null
@@ -0,0 +1,18 @@
+# ====================================================================
+#  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.
+# ====================================================================
+
+org.apache.poi.xslf.usermodel.XSLFSlideShowFactory
\ No newline at end of file
diff --git a/src/resources/scratchpad/META-INF/services/org.apache.poi.sl.usermodel.SlideShowProvider b/src/resources/scratchpad/META-INF/services/org.apache.poi.sl.usermodel.SlideShowProvider
new file mode 100644 (file)
index 0000000..1fcb1ec
--- /dev/null
@@ -0,0 +1,18 @@
+# ====================================================================
+#  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.
+# ====================================================================
+
+org.apache.poi.hslf.usermodel.HSLFSlideShowFactory
\ No newline at end of file
index 16711d0b11de7c69ef7e60d505cf2204b7dd7132..d0e0f88e812ef6b84b3f5d368062a7186f689eba 100644 (file)
@@ -30,9 +30,7 @@ import org.apache.poi.extractor.POIOLE2TextExtractor;
 import org.apache.poi.extractor.POITextExtractor;
 import org.apache.poi.hdgf.extractor.VisioTextExtractor;
 import org.apache.poi.hpbf.extractor.PublisherTextExtractor;
-import org.apache.poi.hslf.usermodel.HSLFShape;
 import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
 import org.apache.poi.hsmf.MAPIMessage;
 import org.apache.poi.hsmf.datatypes.AttachmentChunks;
 import org.apache.poi.hsmf.extractor.OutlookTextExtractor;
@@ -102,7 +100,7 @@ public class OLE2ScratchpadExtractorFactory implements ExtractorProvider {
             }
 
             if (poifsDir.hasEntry(HSLFSlideShow.POWERPOINT_DOCUMENT)) {
-                return new SlideShowExtractor<HSLFShape, HSLFTextParagraph>(SlideShowFactory.create(poifsDir));
+                return new SlideShowExtractor<>((HSLFSlideShow)SlideShowFactory.create(poifsDir));
             }
 
             if (poifsDir.hasEntry("VisioDocument")) {
index 42db16482e74ada46ba830f3f923d769cc616980..936eae064e2ce1f5bdeffb13c5ef72fecbc1f2c7 100644 (file)
 
 package org.apache.poi.hslf.usermodel;
 
+import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 
+import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
 import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.poifs.filesystem.FileMagic;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.sl.usermodel.SlideShowFactory;
+import org.apache.poi.sl.usermodel.SlideShowProvider;
 import org.apache.poi.util.Internal;
 
 /**
@@ -30,11 +35,20 @@ import org.apache.poi.util.Internal;
  */
 @SuppressWarnings("unused")
 @Internal
-public class HSLFSlideShowFactory extends SlideShowFactory {
+public class HSLFSlideShowFactory implements SlideShowProvider<HSLFShape,HSLFTextParagraph> {
 
-    static {
-        SlideShowFactory.createHslfByNode = HSLFSlideShowFactory::createSlideShow;
-        SlideShowFactory.createHslfByPoifs = HSLFSlideShowFactory::createSlideShow;
+    @Override
+    public boolean accepts(FileMagic fm) {
+        return FileMagic.OLE2 == fm;
+    }
+
+    /**
+     * Create a new empty SlideShow
+     *
+     * @return The created SlideShow
+     */
+    public HSLFSlideShow create() {
+        return new HSLFSlideShow();
     }
 
     /**
@@ -51,7 +65,45 @@ public class HSLFSlideShowFactory extends SlideShowFactory {
      * Note that in order to properly release resources the
      * SlideShow should be closed after use.
      */
-    public static HSLFSlideShow createSlideShow(final DirectoryNode root) throws IOException {
-        return new HSLFSlideShow(root);
+    public HSLFSlideShow create(final DirectoryNode root, String password) throws IOException {
+        boolean passwordSet = false;
+        if (password != null) {
+            Biff8EncryptionKey.setCurrentUserPassword(password);
+            passwordSet = true;
+        }
+        try {
+            return new HSLFSlideShow(root);
+        } finally {
+            if (passwordSet) {
+                Biff8EncryptionKey.setCurrentUserPassword(null);
+            }
+        }
+    }
+
+    @Override
+    public HSLFSlideShow create(InputStream inp) throws IOException {
+        return create(inp, null);
+    }
+
+    @Override
+    public HSLFSlideShow create(InputStream inp, String password) throws IOException {
+        POIFSFileSystem fs = new POIFSFileSystem(inp);
+        return create(fs.getRoot(), password);
+    }
+
+    @Override
+    public HSLFSlideShow create(File file, String password, boolean readOnly) throws IOException {
+        boolean passwordSet = false;
+        if (password != null) {
+            Biff8EncryptionKey.setCurrentUserPassword(password);
+            passwordSet = true;
+        }
+        try {
+            return new HSLFSlideShow(new POIFSFileSystem(file, readOnly));
+        } finally {
+            if (passwordSet) {
+                Biff8EncryptionKey.setCurrentUserPassword(null);
+            }
+        }
     }
 }
index 5d53b4bd6253f02ebe0022f3f58d4cfffc7022b5..6158c9de6397497e41a01fb27e9f7cd64c9aa1ae 100644 (file)
@@ -160,8 +160,9 @@ public abstract class BaseTestSlideShow<
     @Test
     public void shapeAndSlideName() throws IOException {
         final String file = "SampleShow.ppt"+(getClass().getSimpleName().contains("XML")?"x":"");
+        //noinspection unchecked
         try (final InputStream is = slTests.openResourceAsStream(file);
-             final SlideShow<S,P> ppt = SlideShowFactory.create(is)) {
+             final SlideShow<S,P> ppt = (SlideShow<S,P>)SlideShowFactory.create(is)) {
             final List<S> shapes1 = ppt.getSlides().get(0).getShapes();
             assertEquals("The Title", shapes1.get(0).getShapeName());
             assertEquals("Another Subtitle", shapes1.get(1).getShapeName());
index d62d787d94d6aaf19913c2390c1c8a43e389d8e9..345bb7906ee37506d905a790aee933682519bad7 100644 (file)
@@ -98,7 +98,7 @@ public abstract class BaseTestSlideShowFactory {
         // from protected POIFS
         if (protectedFile.endsWith(".ppt") || protectedFile.endsWith(".pptx")) {
             POIFSFileSystem poifs = new POIFSFileSystem(fromFile(protectedFile));
-            ss = SlideShowFactory.create(poifs, password);
+            ss = SlideShowFactory.create(poifs.getRoot(), password);
             assertNotNull(ss);
             poifs.close();
             assertCloseDoesNotModifyFile(protectedFile, ss);
@@ -172,13 +172,13 @@ public abstract class BaseTestSlideShowFactory {
             assertArrayEquals(filename + " sample file was modified as a result of closing the slideshow",
                     before, after);
         } catch (AssertionError e) {
-            // if the file after closing is different, then re-set 
-            // the file to the state before in order to not have a dirty SCM 
+            // if the file after closing is different, then re-set
+            // the file to the state before in order to not have a dirty SCM
             // working tree when running this test
             try (FileOutputStream str = new FileOutputStream(_slTests.getFile(filename))) {
                 str.write(before);
             }
-            
+
             throw e;
         }
     }