From adcf7bf53301a9ba1abe7ce67c73e256a4260844 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Tue, 14 Feb 2023 13:51:52 +0000 Subject: [PATCH] add util code to rethrow fatal exceptions git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1907645 13f79535-47bb-0310-9956-ffa450edef68 --- .../examples/hpsf/ReadCustomPropertySets.java | 4 ++ .../apache/poi/xssf/usermodel/XSSFCell.java | 4 ++ .../apache/poi/sl/tests/SLCommonUtils.java | 9 ++- .../org/apache/poi/poifs/nio/CleanerUtil.java | 5 +- .../org/apache/poi/util/ExceptionUtil.java | 60 +++++++++++++++++++ .../java/org/apache/poi/util/XMLHelper.java | 33 ++++++++-- 6 files changed, 107 insertions(+), 8 deletions(-) create mode 100644 poi/src/main/java/org/apache/poi/util/ExceptionUtil.java diff --git a/poi-examples/src/main/java/org/apache/poi/examples/hpsf/ReadCustomPropertySets.java b/poi-examples/src/main/java/org/apache/poi/examples/hpsf/ReadCustomPropertySets.java index ca8cba1ce9..187f434b94 100644 --- a/poi-examples/src/main/java/org/apache/poi/examples/hpsf/ReadCustomPropertySets.java +++ b/poi-examples/src/main/java/org/apache/poi/examples/hpsf/ReadCustomPropertySets.java @@ -29,6 +29,7 @@ import org.apache.poi.hpsf.PropertySetFactory; import org.apache.poi.hpsf.Section; import org.apache.poi.poifs.eventfilesystem.POIFSReader; import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent; +import org.apache.poi.util.ExceptionUtil; /** *

Sample application showing how to read a document's custom property set. @@ -66,6 +67,9 @@ public final class ReadCustomPropertySets { out("No property set stream: \"" + streamName + "\""); return; } catch (Exception ex) { + if (ExceptionUtil.isFatal(ex)) { + ExceptionUtil.rethrow(ex); + } throw new HPSFRuntimeException("Property set stream \"" + streamName + "\": " + ex); } diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFCell.java index 13c1e7848c..42e27b4c97 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFCell.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFCell.java @@ -50,6 +50,7 @@ import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.util.CellUtil; import org.apache.poi.util.Beta; +import org.apache.poi.util.ExceptionUtil; import org.apache.poi.util.Internal; import org.apache.poi.util.LocaleUtil; import org.apache.poi.xssf.model.CalculationChain; @@ -1164,6 +1165,9 @@ public final class XSSFCell extends CellBase { RichTextString rt = _sharedStringSource.getItemAt(sstIndex); return rt.getString(); } catch (Throwable t) { + if (ExceptionUtil.isFatal(t)) { + ExceptionUtil.rethrow(t); + } return ""; } case NUMERIC: diff --git a/poi-ooxml/src/test/java/org/apache/poi/sl/tests/SLCommonUtils.java b/poi-ooxml/src/test/java/org/apache/poi/sl/tests/SLCommonUtils.java index 3c3d243db8..44a95d8a0a 100644 --- a/poi-ooxml/src/test/java/org/apache/poi/sl/tests/SLCommonUtils.java +++ b/poi-ooxml/src/test/java/org/apache/poi/sl/tests/SLCommonUtils.java @@ -25,6 +25,7 @@ import java.io.InputStream; import org.apache.poi.POIDataSamples; import org.apache.poi.sl.usermodel.SlideShow; import org.apache.poi.sl.usermodel.SlideShowFactory; +import org.apache.poi.util.ExceptionUtil; public class SLCommonUtils { private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); @@ -34,7 +35,8 @@ public class SLCommonUtils { try (InputStream is = _slTests.openResourceAsStream(sampleName)) { return SlideShowFactory.create(is); } catch (Exception e) { - throw new RuntimeException(e); + ExceptionUtil.rethrow(e); + return null; //keeps compiler happy, the ExceptionUtil.rethrow(e) will throw an exception } } @@ -48,7 +50,10 @@ public class SLCommonUtils { try { Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow"); return false; - } catch (Exception e) { + } catch (Throwable e) { + if (ExceptionUtil.isFatal(e)) { + ExceptionUtil.rethrow(e); + } return true; } } diff --git a/poi/src/main/java/org/apache/poi/poifs/nio/CleanerUtil.java b/poi/src/main/java/org/apache/poi/poifs/nio/CleanerUtil.java index 11fe068abb..11b2c621d9 100644 --- a/poi/src/main/java/org/apache/poi/poifs/nio/CleanerUtil.java +++ b/poi/src/main/java/org/apache/poi/poifs/nio/CleanerUtil.java @@ -17,6 +17,7 @@ package org.apache.poi.poifs.nio; +import org.apache.poi.util.ExceptionUtil; import org.apache.poi.util.SuppressForbidden; import java.io.IOException; @@ -181,7 +182,9 @@ public final class CleanerUtil { unmapper.invokeExact(buffer); return null; } catch (Throwable t) { - return t; + if (ExceptionUtil.isFatal(t)) { + ExceptionUtil.rethrow(t); + } } }); if (error != null) { diff --git a/poi/src/main/java/org/apache/poi/util/ExceptionUtil.java b/poi/src/main/java/org/apache/poi/util/ExceptionUtil.java new file mode 100644 index 0000000000..01ec1aced2 --- /dev/null +++ b/poi/src/main/java/org/apache/poi/util/ExceptionUtil.java @@ -0,0 +1,60 @@ +/* ==================================================================== + 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.util; + +/** + * Utilitity methods for dealing with exceptions/throwables + * + * @since POI 5.2.4 + */ +public class ExceptionUtil { + private ExceptionUtil() {} + + /** + * It is important never to catch all Throwables. Some like + * {@link InterruptedException} should be rethrown. Based on + * scala.util.control.NonFatal. + * + * @param throwable to check + * @return whether the Throwable is a fatal error + */ + public static boolean isFatal(Throwable throwable) { + //similar to https://www.scala-lang.org/api/2.13.8/scala/util/control/NonFatal$.html + return (throwable instanceof VirtualMachineError + || throwable instanceof ThreadDeath + || throwable instanceof InterruptedException + || throwable instanceof LinkageError); + } + + /** + * Designed to be used in conjunction with {@link #isFatal(Throwable)}. + * This method should be used with care. + * + * @param throwable to check + * @throws Throwable the input throwable if it is an Error or RuntimeException. + * Otherwise wraps the throwable in a RuntimeException. + */ + public static void rethrow(Throwable throwable) { + if (throwable instanceof Error) { + throw (Error) throwable; + } + if (throwable instanceof RuntimeException) { + throw (RuntimeException) throwable; + } + throw new RuntimeException(throwable); + } +} diff --git a/poi/src/main/java/org/apache/poi/util/XMLHelper.java b/poi/src/main/java/org/apache/poi/util/XMLHelper.java index 7ad8e3f0b0..02eecb331b 100644 --- a/poi/src/main/java/org/apache/poi/util/XMLHelper.java +++ b/poi/src/main/java/org/apache/poi/util/XMLHelper.java @@ -163,9 +163,15 @@ public final class XMLHelper { // this also catches NoClassDefFoundError, which may be due to a local class path issue // This may occur if the code is run inside a web container or a restricted JVM // See bug 61170: https://bz.apache.org/bugzilla/show_bug.cgi?id=61170 + if (ExceptionUtil.isFatal(re)) { + ExceptionUtil.rethrow(re); + } logThrowable(re, "Failed to create SAXParserFactory", "-"); throw re; } catch (Exception e) { + if (ExceptionUtil.isFatal(e)) { + ExceptionUtil.rethrow(e); + } logThrowable(e, "Failed to create SAXParserFactory", "-"); throw new IllegalStateException("Failed to create SAXParserFactory", e); } @@ -260,6 +266,9 @@ public final class XMLHelper { } catch (ClassNotFoundException ignored) { // continue without log, this is expected in some setups } catch (Throwable e) { // NOSONAR - also catch things like NoClassDefError here + if (ExceptionUtil.isFatal(e)) { + ExceptionUtil.rethrow(e); + } logThrowable(e, "SAX Feature unsupported", securityManagerClassName); } } @@ -273,9 +282,15 @@ public final class XMLHelper { feature.accept(name, value); return true; } catch (Exception e) { + if (ExceptionUtil.isFatal(e)) { + ExceptionUtil.rethrow(e); + } logThrowable(e, "SAX Feature unsupported", name); - } catch (Error ame) { - logThrowable(ame, "Cannot set SAX feature because outdated XML parser in classpath", name); + } catch (Error e) { + if (ExceptionUtil.isFatal(e)) { + ExceptionUtil.rethrow(e); + } + logThrowable(e, "Cannot set SAX feature because outdated XML parser in classpath", name); } return false; } @@ -285,10 +300,16 @@ public final class XMLHelper { property.accept(name, value); return true; } catch (Exception e) { + if (ExceptionUtil.isFatal(e)) { + ExceptionUtil.rethrow(e); + } logThrowable(e, "SAX Feature unsupported", name); - } catch (Error ame) { + } catch (Error e) { + if (ExceptionUtil.isFatal(e)) { + ExceptionUtil.rethrow(e); + } // ignore all top error object - GraalVM in native mode is not coping with java.xml error message resources - logThrowable(ame, "Cannot set SAX feature because outdated XML parser in classpath", name); + logThrowable(e, "Cannot set SAX feature because outdated XML parser in classpath", name); } return false; } @@ -298,7 +319,9 @@ public final class XMLHelper { property.accept(name, value); return true; } catch (Exception|Error e) { - // ok to ignore + if (ExceptionUtil.isFatal(e)) { + ExceptionUtil.rethrow(e); + } } return false; } -- 2.39.5