* @return output stream for this part
* @see org.apache.poi.openxml4j.opc.internal.MemoryPackagePart
*/
- public OutputStream getOutputStream() {
+ public OutputStream getOutputStream() throws IOException {
OutputStream outStream;
// If this part is a zip package part (read only by design) we convert
// this part into a MemoryPackagePart instance for write purpose.
* Method that gets the input stream for this part.
*
* @return input stream for this part
- * @exception IOException
- * Throws if an IO Exception occur in the implementation
- * method.
+ * @throws IOException
+ * Throws if an IO Exception occur in the implementation method.
*/
protected abstract InputStream getInputStreamImpl() throws IOException;
* Method that gets the output stream for this part.
*
* @return output stream for this part
+ * @throws IOException
+ * Throws if an IO Exception occur in the implementation method.
*/
- protected abstract OutputStream getOutputStreamImpl();
+ protected abstract OutputStream getOutputStreamImpl() throws IOException;
/**
* Save the content of this part and the associated relationships part (if
import org.apache.poi.openxml4j.exceptions.ODFNotOfficeXmlFileException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;
-import org.apache.poi.openxml4j.opc.internal.ContentTypeManager;
-import org.apache.poi.openxml4j.opc.internal.FileHelper;
-import org.apache.poi.openxml4j.opc.internal.MemoryPackagePart;
-import org.apache.poi.openxml4j.opc.internal.PartMarshaller;
-import org.apache.poi.openxml4j.opc.internal.ZipContentTypeManager;
-import org.apache.poi.openxml4j.opc.internal.ZipHelper;
+import org.apache.poi.openxml4j.opc.internal.*;
import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller;
import org.apache.poi.openxml4j.util.ZipArchiveThresholdInputStream;
import org.apache.poi.openxml4j.util.ZipEntrySource;
public final class ZipPackage extends OPCPackage {
private static final String MIMETYPE = "mimetype";
private static final String SETTINGS_XML = "settings.xml";
+ private static boolean useTempFilePackageParts = false;
+ private static boolean encryptTempFilePackageParts = false;
private static final Logger LOG = LogManager.getLogger(ZipPackage.class);
*/
private final ZipEntrySource zipArchive;
+ /**
+ * @param tempFilePackageParts whether to save package part data in temp files to save memory
+ */
+ public void setUseTempFilePackageParts(boolean tempFilePackageParts) {
+ useTempFilePackageParts = tempFilePackageParts;
+ }
+
+ /**
+ * @param encryptTempFiles whether to encrypt temp files
+ */
+ public void setEncryptTempFilePackageParts(boolean encryptTempFiles) {
+ encryptTempFilePackageParts = encryptTempFiles;
+ }
+
+ /**
+ * @return whether package part data is stored in temp files to save memory
+ */
+ public boolean useTempFilePackageParts() {
+ return useTempFilePackageParts;
+ }
+
+ /**
+ * @return whether package part temp files are encrypted
+ */
+ public boolean encryptTempFilePackageParts() {
+ return encryptTempFilePackageParts;
+ }
+
/**
* Constructor. Creates a new, empty ZipPackage.
*/
}
try {
- return new MemoryPackagePart(this, partName, contentType, loadRelationships);
- } catch (InvalidFormatException e) {
+ if (useTempFilePackageParts) {
+ if (encryptTempFilePackageParts) {
+ return new EncryptedTempFilePackagePart(this, partName, contentType, loadRelationships);
+ } else {
+ return new TempFilePackagePart(this, partName, contentType, loadRelationships);
+ }
+ } else {
+ return new MemoryPackagePart(this, partName, contentType, loadRelationships);
+ }
+ } catch (Exception e) {
LOG.atWarn().withThrowable(e).log("Failed to create part {}", partName);
return null;
}
/**
* Get the zip entry of this part.
*
- * @return The zip entry in the zip structure coresponding to this part.
+ * @return The zip entry in the zip structure corresponding to this part.
*/
public ZipArchiveEntry getZipArchive() {
return zipEntry;
--- /dev/null
+/* ====================================================================
+ 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.openxml4j.opc.internal;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackagePartName;
+import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller;
+import org.apache.poi.poifs.crypt.temp.EncryptedTempData;
+import org.apache.poi.util.Beta;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.TempFile;
+
+import java.io.*;
+
+/**
+ * (Experimental) Encrypted Temp File version of a package part.
+ *
+ * @since POI 5.1.0
+ */
+@Beta
+public final class EncryptedTempFilePackagePart extends PackagePart {
+ private static final Logger LOG = LogManager.getLogger(EncryptedTempFilePackagePart.class);
+
+ /**
+ * Storage for the part data.
+ */
+ private EncryptedTempData tempFile;
+
+ /**
+ * Constructor.
+ *
+ * @param pack
+ * The owner package.
+ * @param partName
+ * The part name.
+ * @param contentType
+ * The content type.
+ * @throws InvalidFormatException
+ * If the specified URI is not OPC compliant.
+ * @throws IOException
+ * If temp file cannot be created.
+ */
+ public EncryptedTempFilePackagePart(OPCPackage pack, PackagePartName partName,
+ String contentType) throws InvalidFormatException, IOException {
+ this(pack, partName, contentType, false);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param pack
+ * The owner package.
+ * @param partName
+ * The part name.
+ * @param contentType
+ * The content type.
+ * @param loadRelationships
+ * Specify if the relationships will be loaded.
+ * @throws InvalidFormatException
+ * If the specified URI is not OPC compliant.
+ * @throws IOException
+ * If temp file cannot be created.
+ */
+ public EncryptedTempFilePackagePart(OPCPackage pack, PackagePartName partName,
+ String contentType, boolean loadRelationships)
+ throws InvalidFormatException, IOException {
+ super(pack, partName, new ContentType(contentType), loadRelationships);
+ tempFile = new EncryptedTempData();
+ }
+
+ @Override
+ protected InputStream getInputStreamImpl() throws IOException {
+ return tempFile.getInputStream();
+ }
+
+ @Override
+ protected OutputStream getOutputStreamImpl() throws IOException {
+ return tempFile.getOutputStream();
+ }
+
+ /**
+ * @return EncryptedTempData.getSize() always returns -1
+ */
+ @Override
+ public long getSize() {
+ return -1;
+ }
+
+ @Override
+ public void clear() {
+ try(OutputStream os = getOutputStreamImpl()) {
+ os.write(new byte[0]);
+ } catch (IOException e) {
+ LOG.atWarn().log("Failed to clear data in temp file", e);
+ }
+ }
+
+ @Override
+ public boolean save(OutputStream os) throws OpenXML4JException {
+ return new ZipPartMarshaller().marshall(this, os);
+ }
+
+ @Override
+ public boolean load(InputStream ios) throws InvalidFormatException {
+ try (OutputStream os = getOutputStreamImpl()) {
+ IOUtils.copy(ios, os);
+ } catch(IOException e) {
+ throw new InvalidFormatException(e.getMessage(), e);
+ }
+
+ // All done
+ return true;
+ }
+
+ @Override
+ public void close() {
+ tempFile.dispose();
+ }
+
+ @Override
+ public void flush() {
+ // Do nothing
+ }
+}
@Override
public boolean load(InputStream ios) throws InvalidFormatException {
- try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream()) {
- // Grab the data
- IOUtils.copy(ios, baos);
- // Save it
- data = baos.toByteArray();
- } catch(IOException e) {
- throw new InvalidFormatException(e.getMessage());
- }
-
- // All done
- return true;
+ try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream()) {
+ // Grab the data
+ IOUtils.copy(ios, baos);
+ // Save it
+ data = baos.toByteArray();
+ } catch (IOException e) {
+ throw new InvalidFormatException(e.getMessage());
+ }
+
+ // All done
+ return true;
}
@Override
--- /dev/null
+/* ====================================================================
+ 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.openxml4j.opc.internal;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackagePartName;
+import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller;
+import org.apache.poi.util.Beta;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.TempFile;
+
+import java.io.*;
+
+/**
+ * (Experimental) Temp File version of a package part.
+ *
+ * @since POI 5.1.0
+ */
+@Beta
+public final class TempFilePackagePart extends PackagePart {
+ private static final Logger LOG = LogManager.getLogger(TempFilePackagePart.class);
+
+ /**
+ * Storage for the part data.
+ */
+ private File tempFile;
+
+ /**
+ * Constructor.
+ *
+ * @param pack
+ * The owner package.
+ * @param partName
+ * The part name.
+ * @param contentType
+ * The content type.
+ * @throws InvalidFormatException
+ * If the specified URI is not OPC compliant.
+ * @throws IOException
+ * If temp file cannot be created.
+ */
+ public TempFilePackagePart(OPCPackage pack, PackagePartName partName,
+ String contentType) throws InvalidFormatException, IOException {
+ this(pack, partName, contentType, false);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param pack
+ * The owner package.
+ * @param partName
+ * The part name.
+ * @param contentType
+ * The content type.
+ * @param loadRelationships
+ * Specify if the relationships will be loaded.
+ * @throws InvalidFormatException
+ * If the specified URI is not OPC compliant.
+ * @throws IOException
+ * If temp file cannot be created.
+ */
+ public TempFilePackagePart(OPCPackage pack, PackagePartName partName,
+ String contentType, boolean loadRelationships)
+ throws InvalidFormatException, IOException {
+ super(pack, partName, new ContentType(contentType), loadRelationships);
+ tempFile = TempFile.createTempFile("poi-package-part", ".tmp");
+ }
+
+ @Override
+ protected InputStream getInputStreamImpl() throws IOException {
+ return new FileInputStream(tempFile);
+ }
+
+ @Override
+ protected OutputStream getOutputStreamImpl() throws IOException {
+ return new FileOutputStream(tempFile);
+ }
+
+ @Override
+ public long getSize() {
+ return tempFile.length();
+ }
+
+ @Override
+ public void clear() {
+ try(OutputStream os = getOutputStreamImpl()) {
+ os.write(new byte[0]);
+ } catch (IOException e) {
+ LOG.atWarn().log("Failed to clear data in temp file", e);
+ }
+ }
+
+ @Override
+ public boolean save(OutputStream os) throws OpenXML4JException {
+ return new ZipPartMarshaller().marshall(this, os);
+ }
+
+ @Override
+ public boolean load(InputStream ios) throws InvalidFormatException {
+ try (OutputStream os = getOutputStreamImpl()) {
+ IOUtils.copy(ios, os);
+ } catch(IOException e) {
+ throw new InvalidFormatException(e.getMessage(), e);
+ }
+
+ // All done
+ return true;
+ }
+
+ @Override
+ public void close() {
+ if (!tempFile.delete()) {
+ LOG.atInfo().log("Failed to delete temp file; may already have been closed and deleted");
+ }
+ }
+
+ @Override
+ public void flush() {
+ // Do nothing
+ }
+}
return getPackagePart().getInputStream();
}
- public OutputStream getOutputStream() {
+ public OutputStream getOutputStream() throws IOException {
final PackagePart pp = getPackagePart();
pp.clear();
return pp.getOutputStream();
}
@Override
- public OutputStream getOutputStream() {
+ public OutputStream getOutputStream() throws IOException {
final PackagePart pp = getPackagePart();
pp.clear();
return pp.getOutputStream();