git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1894203 13f79535-47bb-0310-9956-ffa450edef68tags/REL_5_2_0
@@ -518,7 +518,7 @@ public abstract class PackagePart implements RelationshipSource, Comparable<Pack | |||
* @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. | |||
@@ -674,9 +674,8 @@ public abstract class PackagePart implements RelationshipSource, Comparable<Pack | |||
* 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; | |||
@@ -684,8 +683,10 @@ public abstract class PackagePart implements RelationshipSource, Comparable<Pack | |||
* 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 |
@@ -43,12 +43,7 @@ import org.apache.poi.openxml4j.exceptions.NotOfficeXmlFileException; | |||
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; | |||
@@ -63,6 +58,8 @@ import org.apache.poi.util.TempFile; | |||
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); | |||
@@ -72,6 +69,34 @@ public final class ZipPackage extends OPCPackage { | |||
*/ | |||
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. | |||
*/ | |||
@@ -371,8 +396,16 @@ public final class ZipPackage extends OPCPackage { | |||
} | |||
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; | |||
} |
@@ -86,7 +86,7 @@ public class ZipPackagePart extends PackagePart { | |||
/** | |||
* 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; |
@@ -0,0 +1,144 @@ | |||
/* ==================================================================== | |||
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 | |||
} | |||
} |
@@ -113,17 +113,17 @@ public final class MemoryPackagePart extends PackagePart { | |||
@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 |
@@ -0,0 +1,142 @@ | |||
/* ==================================================================== | |||
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 | |||
} | |||
} |
@@ -57,7 +57,7 @@ public class XSLFFontData extends POIXMLDocumentPart { | |||
return getPackagePart().getInputStream(); | |||
} | |||
public OutputStream getOutputStream() { | |||
public OutputStream getOutputStream() throws IOException { | |||
final PackagePart pp = getPackagePart(); | |||
pp.clear(); | |||
return pp.getOutputStream(); |
@@ -59,7 +59,7 @@ public final class XSLFObjectData extends POIXMLDocumentPart implements ObjectDa | |||
} | |||
@Override | |||
public OutputStream getOutputStream() { | |||
public OutputStream getOutputStream() throws IOException { | |||
final PackagePart pp = getPackagePart(); | |||
pp.clear(); | |||
return pp.getOutputStream(); |