package com.alibaba.excel.analysis; import java.io.InputStream; import org.apache.poi.poifs.crypt.Decryptor; import org.apache.poi.poifs.filesystem.DocumentFactoryHelper; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.util.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.excel.analysis.v03.XlsSaxAnalyser; import com.alibaba.excel.analysis.v07.XlsxSaxAnalyser; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.context.AnalysisContextImpl; import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.exception.ExcelAnalysisStopException; import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.ReadWorkbook; import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.util.FileUtils; /** * @author jipengfei */ public class ExcelAnalyserImpl implements ExcelAnalyser { private static final Logger LOGGER = LoggerFactory.getLogger(ExcelAnalyserImpl.class); private AnalysisContext analysisContext; private ExcelExecutor excelExecutor; public ExcelAnalyserImpl(ReadWorkbook readWorkbook) { try { analysisContext = new AnalysisContextImpl(readWorkbook); choiceExcelExecutor(); } catch (RuntimeException e) { finish(); throw e; } catch (Throwable e) { finish(); throw new ExcelAnalysisException(e); } } private void choiceExcelExecutor() throws Exception { ReadWorkbookHolder readWorkbookHolder = analysisContext.readWorkbookHolder(); ExcelTypeEnum excelType = readWorkbookHolder.getExcelType(); if (excelType == null) { excelExecutor = new XlsxSaxAnalyser(analysisContext, null); return; } switch (excelType) { case XLS: POIFSFileSystem poifsFileSystem = null; if (readWorkbookHolder.getFile() != null) { poifsFileSystem = new POIFSFileSystem(readWorkbookHolder.getFile()); } else { poifsFileSystem = new POIFSFileSystem(readWorkbookHolder.getInputStream()); } // So in encrypted excel, it looks like XLS but it's actually XLSX if (poifsFileSystem.getRoot().hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) { InputStream decryptedStream = null; try { decryptedStream = DocumentFactoryHelper.getDecryptedStream(poifsFileSystem.getRoot(), null); excelExecutor = new XlsxSaxAnalyser(analysisContext, decryptedStream); return; } finally { IOUtils.closeQuietly(decryptedStream); // as we processed the full stream already, we can close the filesystem here // otherwise file handles are leaked poifsFileSystem.close(); } } excelExecutor = new XlsSaxAnalyser(analysisContext, poifsFileSystem); break; case XLSX: excelExecutor = new XlsxSaxAnalyser(analysisContext, null); break; default: } } @Override public void analysis(ReadSheet readSheet) { try { analysisContext.currentSheet(excelExecutor, readSheet); try { excelExecutor.execute(); } catch (ExcelAnalysisStopException e) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Custom stop!"); } } analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext); } catch (RuntimeException e) { finish(); throw e; } catch (Throwable e) { finish(); throw new ExcelAnalysisException(e); } } @Override public void finish() { if (analysisContext == null || analysisContext.readWorkbookHolder() == null) { return; } ReadWorkbookHolder readWorkbookHolder = analysisContext.readWorkbookHolder(); try { if (readWorkbookHolder.getReadCache() != null) { readWorkbookHolder.getReadCache().destroy(); } } catch (Throwable t) { throwCanNotCloseIo(t); } try { if (readWorkbookHolder.getOpcPackage() != null) { readWorkbookHolder.getOpcPackage().close(); } } catch (Throwable t) { throwCanNotCloseIo(t); } try { if (readWorkbookHolder.getPoifsFileSystem() != null) { readWorkbookHolder.getPoifsFileSystem().close(); } } catch (Throwable t) { throwCanNotCloseIo(t); } try { if (analysisContext.readWorkbookHolder().getAutoCloseStream() && readWorkbookHolder.getInputStream() != null) { readWorkbookHolder.getInputStream().close(); } } catch (Throwable t) { throwCanNotCloseIo(t); } try { if (readWorkbookHolder.getTempFile() != null) { FileUtils.delete(readWorkbookHolder.getTempFile()); } } catch (Throwable t) { throwCanNotCloseIo(t); } } private void throwCanNotCloseIo(Throwable t) { throw new ExcelAnalysisException("Can not close IO", t); } @Override public com.alibaba.excel.analysis.ExcelExecutor excelExecutor() { return excelExecutor; } @Override public AnalysisContext analysisContext() { return analysisContext; } }