This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit eb79398aaaf7b924d8f337033eb42c85be461241 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Wed Feb 16 11:58:33 2022 +0100 Unify the way RuntimeException are translated to DataStoreException between GeoTIFF and netCDF readers. --- .../org/apache/sis/storage/geotiff/DataCube.java | 2 +- .../apache/sis/internal/netcdf/RasterResource.java | 39 +++----------- .../sis/internal/storage/AbstractGridResource.java | 62 ++++++++++++---------- .../sis/internal/storage/AbstractResource.java | 20 +++---- .../org/apache/sis/storage/CoverageSubset.java | 6 ++- 5 files changed, 59 insertions(+), 70 deletions(-) diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/DataCube.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/DataCube.java index f8a510d..8bcefef 100644 --- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/DataCube.java +++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/DataCube.java @@ -205,7 +205,7 @@ abstract class DataCube extends TiledGridResource implements ResourceOnFileSyste coverage = preload(coverage); } } catch (RuntimeException e) { - throw canNotRead("read", reader.input.filename, domain, e); + throw canNotRead(reader.input.filename, domain, e); } logReadOperation(reader.store.path, coverage.getGridGeometry(), startTime); return coverage; diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java index 4fa11f7..9d615ae 100644 --- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java +++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java @@ -41,12 +41,9 @@ import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.coverage.grid.GridDerivation; import org.apache.sis.coverage.grid.GridRoundingMode; -import org.apache.sis.coverage.grid.DisjointExtentException; import org.apache.sis.coverage.IllegalSampleDimensionException; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.DataStoreContentException; -import org.apache.sis.storage.DataStoreReferencingException; -import org.apache.sis.storage.NoSuchDataException; import org.apache.sis.storage.Resource; import org.apache.sis.math.MathFunctions; import org.apache.sis.measure.MeasurementRange; @@ -622,12 +619,9 @@ public final class RasterResource extends AbstractGridResource implements Resour * @throws DataStoreException if an error occurred while reading the grid coverage data. */ @Override - public GridCoverage read(GridGeometry domain, final int... range) throws DataStoreException { + public GridCoverage read(final GridGeometry domain, final int... range) throws DataStoreException { final long startTime = System.nanoTime(); final RangeArgument rangeIndices = validateRangeArgument(ranges.length, range); - if (domain == null) { - domain = gridGeometry; - } final Variable first = data[bandDimension >= 0 ? 0 : rangeIndices.getFirstSpecified()]; final DataType dataType = first.getDataType(); if (bandDimension < 0) { @@ -647,17 +641,18 @@ public final class RasterResource extends AbstractGridResource implements Resour * • (bandDimension = 0): one variable containing all bands, with bands in the first dimension. * • (bandDimension > 0): one variable containing all bands, with bands in the last dimension. */ + final GridGeometry targetDomain; final DataBuffer imageBuffer; final SampleDimension[] bands = new SampleDimension[rangeIndices.getNumBands()]; int[] bandOffsets = null; // By default, all bands start at index 0. try { final GridDerivation targetGeometry = gridGeometry.derive() .rounding(GridRoundingMode.ENCLOSING) - .subgrid(domain); + .subgrid((domain != null) ? domain : gridGeometry); GridExtent areaOfInterest = targetGeometry.getIntersection(); // Pixel indices of data to read. int[] subsampling = targetGeometry.getSubsampling(); // Slice to read or subsampling to apply. int numBuffers = bands.length; // By default, one variable per band. - domain = targetGeometry.build(); // Adjust user-specified domain to data geometry. + targetDomain = targetGeometry.build(); // Adjust user-specified domain to data geometry. if (bandDimension >= 0) { areaOfInterest = rangeIndices.insertBandDimension(areaOfInterest, bandDimension); subsampling = rangeIndices.insertSubsampling (subsampling, bandDimension); @@ -718,17 +713,8 @@ public final class RasterResource extends AbstractGridResource implements Resour * Convert NIO Buffer into Java2D DataBuffer. May throw various RuntimeException. */ imageBuffer = RasterFactory.wrap(dataType.rasterDataType, sampleValues); - } catch (IOException e) { - throw new DataStoreException(canNotReadFile(), e); - } catch (DisjointExtentException e) { - throw new NoSuchDataException(canNotReadFile(), e); - } catch (RuntimeException e) { // Many exceptions thrown by RasterFactory.wrap(…). - final Exception cause = getReferencingCause(e); - if (cause != null) { - throw new DataStoreReferencingException(canNotReadFile(), cause); - } else { - throw new DataStoreContentException(canNotReadFile(), e); - } + } catch (IOException | RuntimeException e) { + throw canNotRead(getFilename(), domain, e); } /* * At this point the I/O operation is completed and sample values have been stored in a NIO buffer. @@ -738,23 +724,14 @@ public final class RasterResource extends AbstractGridResource implements Resour throw new DataStoreContentException(Errors.getResources(getLocale()).getString(Errors.Keys.UnsupportedType_1, dataType.name())); } final Variable main = data[visibleBand]; - final Raster raster = new Raster(domain, UnmodifiableArrayList.wrap(bands), imageBuffer, + final Raster raster = new Raster(targetDomain, UnmodifiableArrayList.wrap(bands), imageBuffer, String.valueOf(identifier), rangeIndices.getPixelStride(), bandOffsets, visibleBand, main.decoder.convention().getColors(main)); - logReadOperation(location, domain, startTime); + logReadOperation(location, targetDomain, startTime); return raster; } /** - * Returns the error message for a file that can not be read. - * - * @return default error message to use in exceptions. - */ - private String canNotReadFile() { - return Errors.getResources(getLocale()).getString(Errors.Keys.CanNotRead_1, getFilename()); - } - - /** * Returns the name of the netCDF file. This is used for error messages. */ private String getFilename() { diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractGridResource.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractGridResource.java index 3b0754e..a3f95ad 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractGridResource.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractGridResource.java @@ -33,14 +33,15 @@ import org.opengis.metadata.spatial.DimensionNameType; import org.opengis.referencing.operation.TransformException; import org.opengis.util.FactoryException; import org.apache.sis.storage.DataStoreException; +import org.apache.sis.storage.DataStoreContentException; import org.apache.sis.storage.DataStoreReferencingException; -import org.apache.sis.storage.GridCoverageResource; import org.apache.sis.storage.NoSuchDataException; +import org.apache.sis.storage.GridCoverageResource; +import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.DisjointExtentException; import org.apache.sis.coverage.SampleDimension; -import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.math.MathFunctions; import org.apache.sis.measure.Latitude; import org.apache.sis.measure.Longitude; @@ -471,44 +472,51 @@ public abstract class AbstractGridResource extends AbstractResource implements G /** * Creates an exception for a failure to load data. If the failure may be caused by an envelope - * outside the domain of validity, that envelope will be inferred from the {@code request} argument. + * outside the resource domain, that envelope will be inferred from the {@code request} argument. * - * @param caller the method invoking this method, for logging purposes only. - * @param filename name of the file that can not be read. + * @param filename some identification (typically a file name) of the data that can not be read. * @param request the requested domain, or {@code null} if unspecified. * @param cause the cause of the failure, or {@code null} if none. * @return the exception to throw. */ - protected final DataStoreException canNotRead(final String caller, final String filename, - final GridGeometry request, final Exception cause) - { + protected final DataStoreException canNotRead(final String filename, final GridGeometry request, Throwable cause) { + final int DOMAIN = 1, REFERENCING = 2, CONTENT = 3; + int type = 0; // One of above constants, with 0 for "none of above". Envelope bounds = null; - final boolean isDisjoint = (cause instanceof DisjointExtentException); - if (isDisjoint && request != null && request.isDefined(GridGeometry.ENVELOPE)) { - bounds = request.getEnvelope(); + if (cause instanceof DisjointExtentException) { + type = DOMAIN; + if (request != null && request.isDefined(GridGeometry.ENVELOPE)) { + bounds = request.getEnvelope(); + } + } else if (cause instanceof RuntimeException) { + Throwable c = cause.getCause(); + if (isReferencing(c)) { + type = REFERENCING; + cause = c; + } else if (cause instanceof ArithmeticException || cause instanceof RasterFormatException) { + type = CONTENT; + } + } else if (isReferencing(cause)) { + type = REFERENCING; } - final String message = createDisjointDomainMessage(caller, filename, bounds); - if (isDisjoint) { - return new NoSuchDataException(message, cause); - } else { - return new DataStoreException(message, cause); + final String message = createExceptionMessage(filename, bounds); + switch (type) { + case DOMAIN: return new NoSuchDataException(message, cause); + case REFERENCING: return new DataStoreReferencingException(message, cause); + case CONTENT: return new DataStoreContentException(message, cause); + default: return new DataStoreException(message, cause); } } /** - * If the given exception is caused by a {@link FactoryException} or {@link TransformException}, - * returns that cause. Otherwise returns {@code null}. This is a convenience method for deciding - * if an exception should be rethrown as an {@link DataStoreReferencingException}. + * Returns {@code true} if the given exception is {@link FactoryException} or {@link TransformException}. + * This is for deciding if an exception should be rethrown as an {@link DataStoreReferencingException}. * - * @param e the exception for which to inspect the cause. - * @return the cause if it is a referencing problem, or {@code null} otherwise. + * @param cause the exception to verify. + * @return whether the given exception is {@link FactoryException} or {@link TransformException}. */ - protected static Exception getReferencingCause(final RuntimeException e) { - final Throwable cause = e.getCause(); - if (cause instanceof FactoryException || cause instanceof TransformException) { - return (Exception) cause; - } - return null; + private static boolean isReferencing(final Throwable cause) { + return (cause instanceof FactoryException || cause instanceof TransformException); } /** diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java index 057254d..71e8357 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java @@ -225,15 +225,15 @@ public class AbstractResource extends StoreListeners implements Resource { } /** - * Creates an error message for a request outside the resource domain. - * This is used for creating the message of the exception to be thrown. + * Creates an exception message for a resource that can not be read. + * If the error is potentially created by a request out of bounds, + * this method tries to build a message with the problematic coordinates. * - * @param caller the method invoking this method, for logging purposes only. - * @param filename name of the file that can not be read. - * @param request the requested domain, or {@code null} if unknown. - * @return the message if this method found a dimension that does not intersect, or {@code null}. + * @param filename some identification (typically a file name) of the data that can not be read. + * @param request the requested domain, or {@code null} if the problem is not a request out of bounds. + * @return the message to provide in an exception. */ - final String createDisjointDomainMessage(final String caller, final String filename, Envelope request) { + final String createExceptionMessage(final String filename, Envelope request) { String message = Errors.getResources(getLocale()).getString(Errors.Keys.CanNotRead_1, filename); if (request != null) try { Envelope envelope = getEnvelope().orElse(null); @@ -254,8 +254,10 @@ public class AbstractResource extends StoreListeners implements Resource { final String axis; if (crs != null) { axis = IdentifiedObjects.getDisplayName(crs.getCoordinateSystem().getAxis(i), getLocale()); + } else if (i < 3) { + axis = String.valueOf((char) ('x' + i)); } else { - axis = "#" + i; + axis = "#" + (i+1); } if (buffer == null) { buffer = new StringBuilder(message); @@ -269,7 +271,7 @@ public class AbstractResource extends StoreListeners implements Resource { } } } catch (DataStoreException | TransformException e) { - Logging.ignorableException(getLogger(), getClass(), caller, e); + Logging.ignorableException(getLogger(), AbstractResource.class, "createExceptionMessage", e); } return message; } diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageSubset.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageSubset.java index bb5d96e..4c6aba3 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageSubset.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageSubset.java @@ -18,6 +18,8 @@ package org.apache.sis.storage; import java.util.Arrays; import java.util.List; +import org.opengis.util.FactoryException; +import org.opengis.referencing.operation.TransformException; import org.apache.sis.coverage.SampleDimension; import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.GridGeometry; @@ -115,8 +117,8 @@ final class CoverageSubset extends AbstractGridResource { } catch (IllegalArgumentException | IllegalStateException e) { final String msg = Resources.forLocale(getLocale()) .getString(Resources.Keys.CanNotIntersectDataWithQuery_1, getSourceName()); - final Exception cause = getReferencingCause(e); - if (cause != null) { + final Throwable cause = e.getCause(); + if (cause instanceof FactoryException || cause instanceof TransformException) { throw new DataStoreReferencingException(msg, cause); } else if (e instanceof DisjointExtentException) { throw new NoSuchDataException(msg, e);