Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

open methods should use checked exceptions #234

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions src/main/java/com/github/pjfanning/xlsx/StreamingReader.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.pjfanning.xlsx;

import com.github.pjfanning.xlsx.exceptions.CheckedReadException;
import com.github.pjfanning.xlsx.exceptions.OpenException;
import com.github.pjfanning.xlsx.exceptions.ParseException;
import com.github.pjfanning.xlsx.exceptions.ReadException;
Expand Down Expand Up @@ -545,9 +546,10 @@ public Builder setFullFormatRichText(boolean fullFormatRichText) {
*
* @param is input stream to read in
* @return A {@link Workbook} that can be read from
* @throws com.github.pjfanning.xlsx.exceptions.ReadException if there is an issue reading the stream
* @throws IOException if an error occurs while opening the file
* @throws CheckedReadException if an error occurs while reading the file
*/
public Workbook open(InputStream is) throws OpenException, ReadException, ParseException {
public Workbook open(InputStream is) throws IOException, CheckedReadException {
StreamingWorkbookReader workbookReader = new StreamingWorkbookReader(this);
workbookReader.init(is);
return new StreamingWorkbook(workbookReader);
Expand All @@ -559,10 +561,10 @@ public Workbook open(InputStream is) throws OpenException, ReadException, ParseE
*
* @param file file to read in
* @return built streaming reader instance
* @throws com.github.pjfanning.xlsx.exceptions.OpenException if there is an issue opening the file
* @throws com.github.pjfanning.xlsx.exceptions.ReadException if there is an issue reading the file
* @throws IOException if an error occurs while opening the file
* @throws CheckedReadException if an error occurs while reading the file
*/
public Workbook open(File file) throws OpenException, ReadException, ParseException {
public Workbook open(File file) throws IOException, CheckedReadException {
StreamingWorkbookReader workbookReader = new StreamingWorkbookReader(this);
workbookReader.init(file);
return new StreamingWorkbook(workbookReader);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.github.pjfanning.xlsx.exceptions;

/**
* An exception that is thrown if there is a problem reading the Excel file.
*
* @see ReadException
* @since 5.0.0
*/
public class CheckedReadException extends ExcelCheckedException {

public CheckedReadException() {
super();
}

public CheckedReadException(String msg) {
super(msg);
}

public CheckedReadException(Exception e) {
super(e);
}

public CheckedReadException(String msg, Exception e) {
super(msg, e);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.github.pjfanning.xlsx.exceptions;

/**
* A parent class for all the excel-streaming-reader specific Checked Exceptions (i.e. not Runtime Exceptions).
*
* @since 5.0.0
*/
public class ExcelCheckedException extends Exception {

protected ExcelCheckedException() {
super();
}

protected ExcelCheckedException(String msg) {
super(msg);
}

protected ExcelCheckedException(Exception e) {
super(e);
}

protected ExcelCheckedException(String msg, Exception e) {
super(msg, e);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
package com.github.pjfanning.xlsx.exceptions;

/**
* A Runtime Exception that is thrown if there is a problem reading the Excel file.
* This is used in APIs where the method is unable to throw a checked exception.
* <p>
* Before v5.0.0, this exception was used in more places but {@link CheckedReadException} is now used
* where checked exceptions are allowed.
* </p>
* @see CheckedReadException
*/
public class ReadException extends ExcelRuntimeException {

public ReadException() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class StreamingRowIterator implements CloseableIterator<Row> {
final Set<Integer> hiddenColumns, final Map<Integer, Float> columnWidths,
final Set<CellRangeAddress> mergedCells, final Set<HyperlinkData> hyperlinks,
final Map<String, SharedFormula> sharedFormulaMap, final float defaultRowHeight,
final StreamingSheet sheet) throws ParseException {
final StreamingSheet sheet) throws XMLStreamException {
this.streamingSheetReader = streamingSheetReader;
this.sst = sst;
this.stylesTable = stylesTable;
Expand Down Expand Up @@ -118,17 +118,13 @@ private float getDefaultRowHeight() {
*
* @return true if data was read
*/
private boolean getRow() throws ParseException {
try {
rowCache.clear();
while(rowCache.size() < rowCacheSize && parser.hasNext()) {
handleEvent(parser.nextEvent());
}
rowCacheIterator = rowCache.iterator();
return rowCacheIterator.hasNext();
} catch(XMLStreamException e) {
throw new ParseException("Error reading XML stream", e);
private boolean getRow() throws XMLStreamException {
rowCache.clear();
while(rowCache.size() < rowCacheSize && parser.hasNext()) {
handleEvent(parser.nextEvent());
}
rowCacheIterator = rowCache.iterator();
return rowCacheIterator.hasNext();
}

private void handleEvent(XMLEvent event) {
Expand Down Expand Up @@ -630,9 +626,17 @@ private String getAttributeValue(Attribute att) {
return att == null ? null : att.getValue();
}

/**
* @return whether there are more rows
* @throws ParseException if there is an error parsing the underlying data
*/
@Override
public boolean hasNext() throws ParseException {
return (rowCacheIterator != null && rowCacheIterator.hasNext()) || getRow();
try {
return (rowCacheIterator != null && rowCacheIterator.hasNext()) || getRow();
} catch (XMLStreamException e) {
throw new ParseException(e);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,8 @@ public int getNumberOfSheets() {
* {@inheritDoc}
*/
@Override
public Sheet getSheetAt(final int index) throws ReadException {
try {
return reader.getSheetAt(index);
} catch (XMLStreamException|IOException e) {
throw new ReadException(e);
}
public Sheet getSheetAt(final int index) {
return reader.getSheetAt(index);
}

/**
Expand All @@ -122,14 +118,11 @@ public Sheet getSheetAt(final int index) throws ReadException {
* @param name - of the sheet
* @return Sheet with the name provided
* @throws MissingSheetException if no sheet is found with the provided <code>name</code>
* @throws ReadException if there is a problem reading the Excel file
*/
@Override
public Sheet getSheet(String name) throws MissingSheetException, ReadException {
public Sheet getSheet(String name) throws MissingSheetException {
try {
return reader.getSheet(name);
} catch (XMLStreamException|IOException e) {
throw new ReadException(e);
} catch (NoSuchElementException nse) {
throw new MissingSheetException("Failed to find sheet: " + name);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@
import com.github.pjfanning.poi.xssf.streaming.TempFileSharedStringsTable;
import com.github.pjfanning.xlsx.SharedStringsImplementationType;
import com.github.pjfanning.xlsx.StreamingReader.Builder;
import com.github.pjfanning.xlsx.exceptions.ExcelRuntimeException;
import com.github.pjfanning.xlsx.exceptions.MissingSheetException;
import com.github.pjfanning.xlsx.exceptions.CheckedReadException;
import com.github.pjfanning.xlsx.exceptions.NotSupportedException;
import com.github.pjfanning.xlsx.exceptions.OpenException;
import com.github.pjfanning.xlsx.exceptions.ParseException;
import com.github.pjfanning.xlsx.exceptions.ReadException;
import com.github.pjfanning.xlsx.impl.ooxml.OoxmlStrictHelper;
import com.github.pjfanning.xlsx.impl.ooxml.OoxmlReader;
import org.apache.commons.io.IOUtils;
import org.apache.poi.UnsupportedFileFormatException;
import org.apache.poi.ooxml.POIXMLException;
import org.apache.poi.ooxml.POIXMLProperties;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
Expand Down Expand Up @@ -70,11 +69,10 @@ public StreamingWorkbookReader(Builder builder) {
/**
* Initializes the reader with the given input stream.
* @param is the input stream to read from
* @throws OpenException if an error occurs while opening the file
* @throws ReadException if an error occurs while reading the file
* @throws ParseException if an error occurs while parsing the file
* @throws IOException if an error occurs while opening the file
* @throws CheckedReadException if an error occurs while reading the file
*/
public void init(InputStream is) throws OpenException, ReadException, ParseException {
public void init(InputStream is) throws IOException, CheckedReadException {
if (builder.avoidTempFiles()) {
try {
if(builder.getPassword() != null) {
Expand All @@ -86,16 +84,16 @@ public void init(InputStream is) throws OpenException, ReadException, ParseExcep
loadPackage(pkg);
} catch(SAXException e) {
IOUtils.closeQuietly(pkg);
throw new ParseException("Failed to parse stream", e);
throw new CheckedReadException("Failed to parse stream", e);
} catch(IOException e) {
IOUtils.closeQuietly(pkg);
throw new OpenException("Failed to open stream", e);
throw e;
} catch(GeneralSecurityException e) {
IOUtils.closeQuietly(pkg);
throw new ReadException("Unable to read workbook - Decryption failed", e);
throw new CheckedReadException("Unable to read workbook - Decryption failed", e);
} catch(OpenXML4JException | XMLStreamException | RuntimeException e) {
IOUtils.closeQuietly(pkg);
throw new ReadException("Unable to read workbook", e);
throw new CheckedReadException("Unable to read workbook", e);
}
} else {
File f = null;
Expand All @@ -106,7 +104,7 @@ public void init(InputStream is) throws OpenException, ReadException, ParseExcep
}
init(f);
tmp = f;
} catch(OpenException | ReadException e) {
} catch(IOException | CheckedReadException e) {
if (f != null && !f.delete()) {
log.debug("failed to delete temp file");
}
Expand All @@ -115,24 +113,23 @@ public void init(InputStream is) throws OpenException, ReadException, ParseExcep
if (f != null && !f.delete()) {
log.debug("failed to delete temp file");
}
throw new ReadException("Unsupported File Format (only xlsx files are supported)", e);
} catch(IOException | RuntimeException e) {
throw new CheckedReadException("Unsupported File Format (only xlsx files are supported)", e);
} catch(RuntimeException e) {
if (f != null && !f.delete()) {
log.debug("failed to delete temp file");
}
throw new ReadException("Unable to read input stream", e);
throw new CheckedReadException("Unable to read workbook", e);
}
}
}

/**
* Initializes the reader with the given input stream.
* @param f the file to read from
* @throws OpenException if an error occurs while opening the file
* @throws ReadException if an error occurs while reading the file
* @throws ParseException if an error occurs while parsing the file
* @throws IOException if an error occurs while opening the file
* @throws CheckedReadException if an error occurs while reading the file
*/
public void init(File f) throws OpenException, ReadException, ParseException {
public void init(File f) throws IOException, CheckedReadException {
try {
if(builder.getPassword() != null) {
POIFSFileSystem poifs = new POIFSFileSystem(f);
Expand All @@ -143,25 +140,19 @@ public void init(File f) throws OpenException, ReadException, ParseException {
loadPackage(pkg);
} catch(SAXException e) {
IOUtils.closeQuietly(pkg);
throw new ParseException("Failed to parse file", e);
throw new CheckedReadException("Failed to parse file", e);
} catch(IOException e) {
IOUtils.closeQuietly(pkg);
throw new OpenException("Failed to open file", e);
throw e;
} catch(UnsupportedFileFormatException e) {
IOUtils.closeQuietly(pkg);
throw new ReadException("Unsupported File Format (only xlsx files are supported)", e);
} catch(OpenXML4JException | XMLStreamException e) {
IOUtils.closeQuietly(pkg);
throw new ReadException("Unable to read workbook", e);
throw new CheckedReadException("Unsupported File Format (only xlsx files are supported)", e);
} catch(GeneralSecurityException e) {
IOUtils.closeQuietly(pkg);
throw new ReadException("Unable to read workbook - Decryption failed", e);
} catch(ExcelRuntimeException e) {
IOUtils.closeQuietly(pkg);
throw e;
} catch(RuntimeException e) {
throw new CheckedReadException("Unable to read workbook - Decryption failed", e);
} catch(OpenXML4JException | XMLStreamException | RuntimeException e) {
IOUtils.closeQuietly(pkg);
throw new ReadException("Unable to read workbook", e);
throw new CheckedReadException("Unable to read workbook", e);
}
}

Expand All @@ -173,7 +164,8 @@ private OPCPackage decryptWorkbook(POIFSFileSystem poifs) throws IOException, Ge
return OPCPackage.open(d.getDataStream(poifs));
}

private void loadPackage(OPCPackage pkg) throws IOException, OpenXML4JException, SAXException, XMLStreamException {
private void loadPackage(OPCPackage pkg)
throws IOException, CheckedReadException, OpenXML4JException, SAXException, XMLStreamException, POIXMLException {
strictFormat = pkg.isStrictOoxmlFormat();
ooxmlReader = new OoxmlReader(builder, pkg, strictFormat);
if (strictFormat) {
Expand Down Expand Up @@ -240,10 +232,8 @@ private List<StreamingSheet> loadSheets() {
* @param idx index (0 based)
* @return the sheet at the given index
* @throws MissingSheetException if a sheet at the given index does not exist
* @throws IOException should never be thrown
* @throws XMLStreamException should never be thrown
*/
public StreamingSheet getSheetAt(final int idx) throws MissingSheetException, IOException, XMLStreamException {
public StreamingSheet getSheetAt(final int idx) throws MissingSheetException {
if (sheets != null && sheets.size() > idx) {
return sheets.get(idx);
} else {
Expand All @@ -261,10 +251,8 @@ public StreamingSheet getSheetAt(final int idx) throws MissingSheetException, IO
* @param name the name of the sheet to return
* @return the sheet with the given name
* @throws MissingSheetException if a sheet with the given name does not exist
* @throws IOException should never be thrown
* @throws XMLStreamException should never be thrown
*/
public StreamingSheet getSheet(final String name) throws MissingSheetException, IOException, XMLStreamException {
public StreamingSheet getSheet(final String name) throws MissingSheetException {
final int idx = ooxmlReader.getSheetIndex(name);
return getSheetAt(idx);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
package com.github.pjfanning.xlsx.impl.ooxml;

import com.github.pjfanning.xlsx.exceptions.ReadException;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Properties;

@Beta
public class OoXmlStrictConverterUtils {
@Internal
final class OoXmlStrictConverterUtils {

private OoXmlStrictConverterUtils() {}

public static boolean isBlank(final String str) {
static boolean isBlank(final String str) {
return str == null || str.trim().length() == 0;
}

public static boolean isNotBlank(final String str) {
static boolean isNotBlank(final String str) {
return !isBlank(str);
}

public static Properties readMappings() throws ReadException {
static Properties readMappings() throws ReadException {
Properties props = new Properties();
try(InputStream is = OoXmlStrictConverterUtils.class.getResourceAsStream("/ooxml-strict-mappings.properties");
BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.ISO_8859_1))) {
Expand Down
Loading