123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- /* ====================================================================
- 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 static org.apache.poi.extractor.ExtractorFactory.OOXML_PACKAGE;
- 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.poifs.crypt.Decryptor;
- import org.apache.poi.poifs.filesystem.DirectoryNode;
- import org.apache.poi.poifs.filesystem.FileMagic;
- import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-
- public final class SlideShowFactory {
-
- private static class Singleton {
- private static final SlideShowFactory INSTANCE = new SlideShowFactory();
- }
-
- private interface ProviderMethod {
- SlideShow<?,?> create(SlideShowProvider<?,?> prov) throws IOException;
- }
-
- private final List<SlideShowProvider<?,?>> provider = new ArrayList<>();
-
- private SlideShowFactory() {
- ClassLoader cl = SlideShowFactory.class.getClassLoader();
- ServiceLoader.load(SlideShowProvider.class, cl).forEach(provider::add);
- }
-
- /**
- * 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 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
- *
- * @return The created SlideShow
- *
- * @throws IOException if an error occurs while reading the data
- */
- public static SlideShow<?,?> create(POIFSFileSystem fs) throws IOException {
- return create(fs, null);
- }
-
- /**
- * Creates a SlideShow from the given POIFSFileSystem, which may
- * 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.
- *
- * @return The created SlideShow
- *
- * @throws IOException if an error occurs while reading the data
- */
- private static SlideShow<?,?> create(final POIFSFileSystem fs, String password) throws IOException {
- return create(fs.getRoot(), password);
- }
-
-
- /**
- * Creates a SlideShow from the given DirectoryNode.
- *
- * @param root The {@link DirectoryNode} to start reading the document from
- *
- * @return The created SlideShow
- *
- * @throws IOException if an error occurs while reading the data
- */
- public static SlideShow<?,?> create(final DirectoryNode root) throws IOException {
- return create(root, null);
- }
-
-
- /**
- * Creates a SlideShow from the given DirectoryNode, which may
- * be password protected
- *
- * @param root The {@link DirectoryNode} to start reading the document from
- * @param password The password that should be used or null if no password is necessary.
- *
- * @return The created SlideShow
- *
- * @throws IOException if an error occurs while reading the data
- */
- 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) || root.hasEntry(OOXML_PACKAGE)) {
- return wp(FileMagic.OOXML, w -> w.create(root, password));
- } else {
- return wp(FileMagic.OLE2, w -> w.create(root, password));
- }
- }
-
- /**
- * Creates the appropriate HSLFSlideShow / XSLFSlideShow from
- * the given InputStream.
- *
- * <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
- * SlideShow 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.
- *
- * @param inp The {@link InputStream} to read data from.
- *
- * @return The created SlideShow
- *
- * @throws IOException if an error occurs while reading the data
- * @throws EncryptedDocumentException If the SlideShow<?,?> given is password protected
- */
- public static SlideShow<?,?> create(InputStream inp) throws IOException, EncryptedDocumentException {
- return create(inp, null);
- }
-
- /**
- * Creates the appropriate HSLFSlideShow / XSLFSlideShow from
- * the given InputStream, which may be password protected.
- *
- * <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
- * SlideShow 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.</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 SlideShow
- *
- * @throws IOException if an error occurs while reading the data
- * @throws EncryptedDocumentException If the wrong password is given for a protected file
- */
- public static SlideShow<?,?> create(InputStream inp, String password) throws IOException, EncryptedDocumentException {
- InputStream is = FileMagic.prepareToCheckMagic(inp);
- 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 / 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.
- *
- * @param file The file to read data from.
- *
- * @return The created SlideShow
- *
- * @throws IOException if an error occurs while reading the data
- * @throws EncryptedDocumentException If the SlideShow given is password protected
- */
- public static SlideShow<?,?> create(File file) throws IOException, EncryptedDocumentException {
- return create(file, null);
- }
-
- /**
- * 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
- * SlideShow 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.
- *
- * @return The created SlideShow
- *
- * @throws IOException if an error occurs while reading the data
- * @throws EncryptedDocumentException If the wrong password is given for a protected file
- */
- public static SlideShow<?,?> create(File file, String password) throws IOException, EncryptedDocumentException {
- return create(file, password, false);
- }
-
- /**
- * 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
- * SlideShow 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 SlideShow should be opened in read-only mode to avoid writing back
- * changes when the document is closed.
- *
- * @return The created SlideShow
- *
- * @throws IOException if an error occurs while reading the data
- * @throws EncryptedDocumentException If the wrong password is given for a protected file
- */
- public static SlideShow<?,?> create(File file, String password, boolean readOnly) throws IOException, EncryptedDocumentException {
- if (!file.exists()) {
- throw new FileNotFoundException(file.toString());
- }
-
- if (file.length() == 0) {
- throw new EmptyFileException();
- }
-
- 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)) {
- DirectoryNode root = fs.getRoot();
- ooxmlEnc = root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY) || root.hasEntry(OOXML_PACKAGE);
- }
- return wp(ooxmlEnc ? FileMagic.OOXML : fm, w -> w.create(file, password, readOnly));
- }
-
- return null;
- }
-
-
-
- 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);
- }
-
- public static void addProvider(SlideShowProvider<?,?> provider){
- Singleton.INSTANCE.provider.add(provider);
- }
-
- public static void removeProvider(Class<? extends SlideShowProvider> provider){
- Singleton.INSTANCE.provider.removeIf(p -> p.getClass().getName().equals(provider.getName()));
- }
- }
|