2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one or more
4 * contributor license agreements. See the NOTICE file distributed with
5 * this work for additional information regarding copyright ownership.
6 * The ASF licenses this file to You under the Apache License, Version 2.0
7 * (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 * ====================================================================
20 package org.apache.poi.xssf.streaming;
22 import static java.nio.charset.StandardCharsets.UTF_8;
23 import static org.junit.jupiter.api.Assertions.assertEquals;
24 import static org.junit.jupiter.api.Assertions.assertFalse;
25 import static org.junit.jupiter.api.Assertions.assertTrue;
28 import java.io.FileInputStream;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.OutputStream;
32 import java.util.List;
34 import org.apache.commons.io.output.NullOutputStream;
35 import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
36 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
37 import org.apache.poi.openxml4j.opc.OPCPackage;
38 import org.apache.poi.openxml4j.util.ZipEntrySource;
39 import org.apache.poi.poifs.crypt.temp.AesZipFileZipEntrySource;
40 import org.apache.poi.poifs.crypt.temp.EncryptedTempData;
41 import org.apache.poi.poifs.crypt.temp.SXSSFWorkbookWithCustomZipEntrySource;
42 import org.apache.poi.util.IOUtils;
43 import org.apache.poi.xssf.usermodel.XSSFCell;
44 import org.apache.poi.xssf.usermodel.XSSFRow;
45 import org.apache.poi.xssf.usermodel.XSSFSheet;
46 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
47 import org.junit.jupiter.api.Test;
50 * This class tests that an SXSSFWorkbook can be written and read where all temporary disk I/O
51 * is encrypted, but the final saved workbook is not encrypted
53 public final class TestSXSSFWorkbookWithCustomZipEntrySource {
55 final String sheetName = "TestSheet1";
56 final String cellValue = "customZipEntrySource";
58 // write an unencrypted workbook to disk, but any temporary files are encrypted
60 void customZipEntrySource() throws IOException {
61 UnsynchronizedByteArrayOutputStream os = UnsynchronizedByteArrayOutputStream.builder().setBufferSize(8192).get();
62 try (SXSSFWorkbookWithCustomZipEntrySource workbook = new SXSSFWorkbookWithCustomZipEntrySource()) {
63 SXSSFSheet sheet1 = workbook.createSheet(sheetName);
64 SXSSFRow row1 = sheet1.createRow(1);
65 SXSSFCell cell1 = row1.createCell(1);
66 cell1.setCellValue(cellValue);
71 try (XSSFWorkbook xwb = new XSSFWorkbook(os.toInputStream())) {
72 XSSFSheet xs1 = xwb.getSheetAt(0);
73 assertEquals(sheetName, xs1.getSheetName());
74 XSSFRow xr1 = xs1.getRow(1);
75 XSSFCell xc1 = xr1.getCell(1);
76 assertEquals(cellValue, xc1.getStringCellValue());
80 // write an encrypted workbook to disk, and encrypt any temporary files as well
82 void customZipEntrySourceForWriteAndRead() throws IOException, InvalidFormatException {
83 EncryptedTempData tempData = new EncryptedTempData();
84 try (SXSSFWorkbookWithCustomZipEntrySource workbook = new SXSSFWorkbookWithCustomZipEntrySource()) {
85 SXSSFSheet sheet1 = workbook.createSheet(sheetName);
86 SXSSFRow row1 = sheet1.createRow(1);
87 SXSSFCell cell1 = row1.createCell(1);
88 cell1.setCellValue(cellValue);
89 try (OutputStream os = tempData.getOutputStream()) {
95 try (InputStream is = tempData.getInputStream();
96 ZipEntrySource zipEntrySource = AesZipFileZipEntrySource.createZipEntrySource(is)) {
98 try (OPCPackage opc = OPCPackage.open(zipEntrySource);
99 XSSFWorkbook xwb = new XSSFWorkbook(opc)) {
100 XSSFSheet xs1 = xwb.getSheetAt(0);
101 assertEquals(sheetName, xs1.getSheetName());
102 XSSFRow xr1 = xs1.getRow(1);
103 XSSFCell xc1 = xr1.getCell(1);
104 assertEquals(cellValue, xc1.getStringCellValue());
110 void validateTempFilesAreEncrypted() throws IOException {
111 TempFileRecordingSXSSFWorkbookWithCustomZipEntrySource workbook = new TempFileRecordingSXSSFWorkbookWithCustomZipEntrySource();
112 SXSSFSheet sheet1 = workbook.createSheet(sheetName);
113 SXSSFRow row1 = sheet1.createRow(1);
114 SXSSFCell cell1 = row1.createCell(1);
115 cell1.setCellValue(cellValue);
116 workbook.write(NullOutputStream.INSTANCE);
118 List<File> tempFiles = workbook.getTempFiles();
119 assertEquals(1, tempFiles.size());
120 File tempFile = tempFiles.get(0);
121 assertTrue(tempFile.exists(), "tempFile exists?");
122 try (InputStream stream = new FileInputStream(tempFile)) {
123 byte[] data = IOUtils.toByteArray(stream);
124 String text = new String(data, UTF_8);
125 assertFalse(text.contains(sheetName));
126 assertFalse(text.contains(cellValue));
129 assertFalse(tempFile.exists(), "tempFile deleted after dispose?");