sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 02/03: Replace a few `getLogger("org.apache.sis.foo")` calls by a static `Logger` constant. Use the logger provided by `DataStoreProvider.getLogger()` when applicable. Add a log when reading a netCDF file as a `GridCoverage`.
Date Tue, 24 Nov 2020 22:25:15 GMT
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 07f4511344986a662486512a0161bf5afb4d9a84
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Tue Nov 24 19:43:31 2020 +0100

    Replace a few `getLogger("org.apache.sis.foo")` calls by a static `Logger` constant.
    Use the logger provided by `DataStoreProvider.getLogger()` when applicable.
    Add a log when reading a netCDF file as a `GridCoverage`.
---
 .../org/apache/sis/coverage/grid/GridGeometry.java |  6 +-
 .../java/org/apache/sis/internal/jdk9/JDK9.java    | 13 +++++
 .../org/apache/sis/internal/system/Modules.java    |  5 ++
 .../sis/internal/util/StandardDateFormat.java      |  4 ++
 .../org/apache/sis/internal/netcdf/Decoder.java    | 21 +++++--
 .../org/apache/sis/internal/netcdf/Linearizer.java |  3 +-
 .../apache/sis/internal/netcdf/RasterResource.java |  5 +-
 .../sis/storage/netcdf/NetcdfStoreProvider.java    |  2 +-
 .../apache/sis/internal/shapefile/AutoChecker.java |  3 +-
 .../internal/shapefile/ShapefileByteReader.java    |  3 +-
 .../sis/storage/shapefile/InputFeatureStream.java  |  3 +-
 .../sis/internal/sql/feature/PostGISMapping.java   |  7 ++-
 .../sis/internal/sql/feature/SpatialFunctions.java |  5 +-
 .../apache/sis/internal/sql/feature/StreamSQL.java |  5 +-
 .../sis/internal/storage/AbstractGridResource.java | 68 +++++++++++++++++++++-
 .../org/apache/sis/internal/storage/Resources.java |  5 ++
 .../sis/internal/storage/Resources.properties      |  1 +
 .../sis/internal/storage/Resources_fr.properties   |  1 +
 .../sis/internal/storage/StoreUtilities.java       |  9 +++
 .../apache/sis/internal/storage/URIDataStore.java  |  3 +-
 .../storage/folder/FolderStoreProvider.java        |  3 +-
 .../sis/internal/storage/io/ChannelFactory.java    |  5 +-
 .../org/apache/sis/storage/DataStoreProvider.java  |  8 ++-
 .../org/apache/sis/storage/StorageConnector.java   |  4 +-
 .../apache/sis/storage/event/StoreListeners.java   | 10 +++-
 25 files changed, 164 insertions(+), 38 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
index 6aa28df..522a87b 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
@@ -887,9 +887,9 @@ public class GridGeometry implements LenientComparable, Serializable {
      * contains an horizontal component such as a geographic or projected CRS.
      *
      * <div class="note"><b>API note:</b>
-     * this method does not throw {@link IncompleteGridGeometryException} because the geographic
extent may be absent
-     * even with a complete grid geometry. This is because grid geometries are not required
to have an spatial component
-     * on Earth surface; a raster could be a vertical profile for example.</div>
+     * this method does not throw {@link IncompleteGridGeometryException} because the geographic
extent
+     * may be absent even with a complete grid geometry. Grid geometries are not required
to have a
+     * spatial component on Earth surface; a raster could be a vertical profile for example.</div>
      *
      * @return the geographic bounding box in "real world" coordinates.
      */
diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/jdk9/JDK9.java b/core/sis-utility/src/main/java/org/apache/sis/internal/jdk9/JDK9.java
index fa9c45a..1137017 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/internal/jdk9/JDK9.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/internal/jdk9/JDK9.java
@@ -31,6 +31,8 @@ import java.util.HashSet;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.Map;
+import java.util.Optional;
+import java.util.function.Consumer;
 import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.internal.util.UnmodifiableArrayList;
 
@@ -52,6 +54,17 @@ public final class JDK9 {
     }
 
     /**
+     * Placeholder for {@link Optional#ifPresentOrElse(Consumer, Runnable)}.
+     */
+    public static <T> void ifPresentOrElse(Optional<T> optional, Consumer<?
super T> action, Runnable emptyAction) {
+        if (optional.isPresent()) {
+            action.accept(optional.get());
+        } else {
+            emptyAction.run();
+        }
+    }
+
+    /**
      * Placeholder for {@code List.of(...)}.
      *
      * @param  <E>       type of elements.
diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/system/Modules.java b/core/sis-utility/src/main/java/org/apache/sis/internal/system/Modules.java
index 22e59d7..3cbcf56 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/internal/system/Modules.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/internal/system/Modules.java
@@ -85,6 +85,11 @@ public final class Modules {
     /**
      * The {@value} module name.
      */
+    public static final String SHAPEFILE = "org.apache.sis.shapefile";
+
+    /**
+     * The {@value} module name.
+     */
     public static final String GDAL = "org.apache.sis.storage.gdal";
 
     /**
diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/util/StandardDateFormat.java
b/core/sis-utility/src/main/java/org/apache/sis/internal/util/StandardDateFormat.java
index 284bab4..75fd103 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/internal/util/StandardDateFormat.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/internal/util/StandardDateFormat.java
@@ -226,21 +226,25 @@ replace:    if (Character.isWhitespace(c)) {
 
     /**
      * The length of a day in number of milliseconds.
+     * Can be casted to {@code float} with exact precision.
      */
     public static final int MILLISECONDS_PER_DAY = 24*60*60*1000;
 
     /**
      * Number of milliseconds in one second.
+     * Can be casted to {@code float} with exact precision.
      */
     public static final int MILLIS_PER_SECOND = 1000;
 
     /**
      * Number of nanoseconds in one millisecond.
+     * Can be casted to {@code float} with exact precision.
      */
     public static final int NANOS_PER_MILLISECOND = 1000000;
 
     /**
      * Number of nanoseconds in one second.
+     * Can be casted to {@code float} with exact precision.
      */
     public static final int NANOS_PER_SECOND = 1000000000;
 
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
index 669d1e4..183569e 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
@@ -26,6 +26,8 @@ import java.util.Date;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
 import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import java.util.logging.Level;
 import java.io.Closeable;
 import java.io.IOException;
 import java.nio.file.Path;
@@ -62,6 +64,11 @@ import ucar.nc2.constants.CF;
  */
 public abstract class Decoder extends ReferencingFactoryContainer implements Closeable {
     /**
+     * The logger to use for messages other than warnings specific to the file being read.
+     */
+    static final Logger LOGGER = Logging.getLogger(Modules.NETCDF);
+
+    /**
      * The format name to use in error message. We use lower-case "n" because it seems to
be what the netCDF community uses.
      * By contrast, {@code NetcdfStoreProvider} uses upper-case "N" because it is considered
at the beginning of sentences.
      */
@@ -491,11 +498,15 @@ public abstract class Decoder extends ReferencingFactoryContainer implements
Clo
      */
     final void performance(final Class<?> caller, final String method, final short
resourceKey, long time) {
         time = System.nanoTime() - time;
-        final LogRecord record = resources().getLogRecord(
-                PerformanceLevel.forDuration(time, TimeUnit.NANOSECONDS), resourceKey,
-                getFilename(), time / (double) StandardDateFormat.NANOS_PER_SECOND);
-        record.setLoggerName(Modules.NETCDF);
-        Logging.log(caller, method, record);
+        final Level level = PerformanceLevel.forDuration(time, TimeUnit.NANOSECONDS);
+        if (LOGGER.isLoggable(level)) {
+            final LogRecord record = resources().getLogRecord(level, resourceKey,
+                    getFilename(), time / (double) StandardDateFormat.NANOS_PER_SECOND);
+            record.setLoggerName(Modules.NETCDF);
+            record.setSourceClassName(caller.getCanonicalName());
+            record.setSourceMethodName(method);
+            LOGGER.log(record);
+        }
     }
 
     /**
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Linearizer.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Linearizer.java
index aff8c9e..eaa8cc1 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Linearizer.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Linearizer.java
@@ -27,7 +27,6 @@ import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.referencing.operation.builder.LocalizationGridBuilder;
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.system.DefaultFactories;
-import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.logging.Logging;
 
@@ -167,6 +166,6 @@ public enum Linearizer {
      * happens anyway, do not cause the whole netCDF reader to fail for all files because
of this error.
      */
     private static void warning(final Exception e) {
-        Logging.unexpectedException(Logging.getLogger(Modules.NETCDF), Variable.class, "getGridGeometry",
e);
+        Logging.unexpectedException(Decoder.LOGGER, Variable.class, "getGridGeometry", e);
     }
 }
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 7751946..bd6c364 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
@@ -609,6 +609,7 @@ public final class RasterResource extends AbstractGridResource implements
Resour
      */
     @Override
     public GridCoverage read(GridGeometry domain, final int... range) throws DataStoreException
{
+        final long startTime = System.nanoTime();
         final RangeArgument rangeIndices = validateRangeArgument(ranges.length, range);
         if (domain == null) {
             domain = gridGeometry;
@@ -718,8 +719,10 @@ public final class RasterResource extends AbstractGridResource implements
Resour
         if (imageBuffer == null) {
             throw new DataStoreContentException(Errors.getResources(getLocale()).getString(Errors.Keys.UnsupportedType_1,
dataType.name()));
         }
-        return new Raster(domain, UnmodifiableArrayList.wrap(bands), imageBuffer,
+        final Raster raster = new Raster(domain, UnmodifiableArrayList.wrap(bands), imageBuffer,
                 rangeIndices.getPixelStride(), bandOffsets, String.valueOf(identifier));
+        logReadOperation(location, domain, startTime);
+        return raster;
     }
 
     /**
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
index 4a7d090..49f7072 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
@@ -218,7 +218,7 @@ public class NetcdfStoreProvider extends DataStoreProvider {
                          * in which case UCAR tries to open it as a file even if it is not
a file. For example
                          * we get this exception for "jar:file:/file.jar!/entry.nc".
                          */
-                        Logging.recoverableException(Logging.getLogger(Modules.NETCDF), netcdfFileClass,
"canOpen", cause);
+                        Logging.recoverableException(getLogger(), netcdfFileClass, "canOpen",
cause);
                         return ProbeResult.UNSUPPORTED_STORAGE;
                     }
                     throw new DataStoreException(e);                        // The cause
may be IOException.
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/AutoChecker.java
b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/AutoChecker.java
index abf386f..b656511 100644
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/AutoChecker.java
+++ b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/AutoChecker.java
@@ -23,6 +23,7 @@ import java.util.Objects;
 import java.util.ResourceBundle;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import org.apache.sis.internal.system.Modules;
 
 import org.apache.sis.util.logging.Logging;
 
@@ -34,7 +35,7 @@ import org.apache.sis.util.logging.Logging;
  */
 public abstract class AutoChecker {
     /** Logger. */
-    private static Logger LOGGER = Logging.getLogger(AutoChecker.class);
+    static Logger LOGGER = Logging.getLogger(Modules.SHAPEFILE);
 
     /**
      * Format a resource bundle message.
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/ShapefileByteReader.java
b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/ShapefileByteReader.java
index e1fad49..f07a1c2 100644
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/ShapefileByteReader.java
+++ b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/ShapefileByteReader.java
@@ -30,7 +30,6 @@ import org.apache.sis.feature.DefaultFeatureType;
 import org.apache.sis.internal.shapefile.jdbc.*;
 import org.apache.sis.storage.shapefile.InvalidShapefileFormatException;
 import org.apache.sis.storage.shapefile.ShapeTypeEnum;
-import org.apache.sis.util.logging.Logging;
 import org.opengis.feature.Feature;
 
 import com.esri.core.geometry.*;
@@ -320,7 +319,7 @@ public class ShapefileByteReader extends CommonByteReader<InvalidShapefileFormat
 
         // Handle multiple polygon parts.
         if (numParts > 1) {
-            Logger log = Logging.getLogger(ShapefileByteReader.class);
+            Logger log = AutoChecker.LOGGER;
 
             if (log.isLoggable(Level.FINER)) {
                 String format = "Polygon with multiple linear rings encountered at position
{0,number} with {1,number} parts.";
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/storage/shapefile/InputFeatureStream.java
b/storage/sis-shapefile/src/main/java/org/apache/sis/storage/shapefile/InputFeatureStream.java
index 1d19f09..968b9c7 100644
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/storage/shapefile/InputFeatureStream.java
+++ b/storage/sis-shapefile/src/main/java/org/apache/sis/storage/shapefile/InputFeatureStream.java
@@ -36,6 +36,7 @@ import org.apache.sis.internal.shapefile.jdbc.sql.SQLIllegalParameterException;
 import org.apache.sis.internal.shapefile.jdbc.sql.SQLInvalidStatementException;
 import org.apache.sis.internal.shapefile.jdbc.sql.SQLUnsupportedParsingFeatureException;
 import org.apache.sis.internal.shapefile.jdbc.statement.DBFStatement;
+import org.apache.sis.internal.system.Modules;
 import org.apache.sis.storage.DataStoreClosedException;
 import org.apache.sis.util.logging.Logging;
 import org.opengis.feature.Feature;
@@ -53,7 +54,7 @@ import org.opengis.feature.Feature;
  */
 public class InputFeatureStream extends InputStream {
     /** Logger. */
-    private static Logger LOGGER = Logging.getLogger(InputFeatureStream.class);
+    private static final Logger LOGGER = Logging.getLogger(Modules.SHAPEFILE);
 
     /** Resource bundle. */
     private ResourceBundle rsc = ResourceBundle.getBundle(InputFeatureStream.class.getName());
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/PostGISMapping.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/PostGISMapping.java
index a2dffbf..5be1131 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/PostGISMapping.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/PostGISMapping.java
@@ -33,6 +33,7 @@ import org.apache.sis.setup.GeometryLibrary;
 import org.apache.sis.util.collection.BackingStoreException;
 import org.apache.sis.util.collection.Cache;
 import org.apache.sis.util.logging.Logging;
+import org.apache.sis.internal.system.Modules;
 
 import static org.apache.sis.internal.sql.feature.OGC06104r4.Reader;
 import static org.apache.sis.internal.sql.feature.OGC06104r4.getGeometricClass;
@@ -46,8 +47,8 @@ import static org.apache.sis.internal.sql.feature.OGC06104r4.getGeometricClass;
  * </ul>
  *
  * @author Alexis Manin (Geomatys)
- * @version 2.0
- * @since   2.0
+ * @version 1.1
+ * @since   1.1
  * @module
  */
 public final class PostGISMapping implements DialectMapping {
@@ -129,7 +130,7 @@ public final class PostGISMapping implements DialectMapping {
             try {
                 checkPostGISVersion(c);
             } catch (SQLException e) {
-                final Logger logger = Logging.getLogger("org.apache.sis.internal.sql");
+                final Logger logger = Logging.getLogger(Modules.SQL);
                 logger.warning("No compatible PostGIS version found. Binding deactivated.
See debug logs for more information");
                 logger.log(Level.FINE, "Cannot determine PostGIS version", e);
                 return Optional.empty();
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/SpatialFunctions.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/SpatialFunctions.java
index 182e206..99da6da 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/SpatialFunctions.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/SpatialFunctions.java
@@ -29,6 +29,7 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
 
 import org.apache.sis.internal.metadata.sql.Dialect;
 import org.apache.sis.internal.metadata.sql.Reflection;
+import org.apache.sis.internal.system.Modules;
 import org.apache.sis.setup.GeometryLibrary;
 import org.apache.sis.util.logging.Logging;
 
@@ -41,7 +42,7 @@ import org.apache.sis.util.logging.Logging;
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
  * @since   1.0
  * @module
  */
@@ -138,7 +139,7 @@ class SpatialFunctions {
                 try {
                     return new OGC06104r4.Spi().create(geomDriver, c);
                 } catch (SQLException e) {
-                    final Logger logger = Logging.getLogger("org.apache.sis.internal.sql");
+                    final Logger logger = Logging.getLogger(Modules.SQL);
                     logger.warning("No supported geometric binding. For more information,
activate debug logs.");
                     logger.log(Level.FINE, "Error while creating default Geometric binding
over SQL", e);
                 }
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/StreamSQL.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/StreamSQL.java
index c3dc7f0..6fad2e6 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/StreamSQL.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/StreamSQL.java
@@ -41,6 +41,7 @@ import org.opengis.feature.Feature;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.util.collection.BackingStoreException;
 import org.apache.sis.util.logging.Logging;
+import org.apache.sis.internal.system.Modules;
 
 import static org.apache.sis.internal.sql.feature.Database.connectReadOnly;
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
@@ -55,7 +56,7 @@ import static org.apache.sis.util.ArgumentChecks.ensurePositive;
  * of stream elements is not bound 1 to 1 to query result rows).
  *
  * @author Alexis Manin (Geomatys)
- * @version 2.0
+ * @version 1.1
  * @since   1.0
  * @module
  *
@@ -72,7 +73,7 @@ final class StreamSQL extends StreamWrapper<Feature> {
 
     private long limit, offset;
 
-    private Consumer<SQLException> warningConsumer = e -> Logging.getLogger("sis.sql").log(Level.FINE,
"Cannot properly close a connection", e);
+    private Consumer<SQLException> warningConsumer = e -> Logging.getLogger(Modules.SQL).log(Level.FINE,
"Cannot properly close a connection", e);
 
     StreamSQL(final Table source, boolean parallel) {
         this(new Features.Builder(source), source.source, parallel);
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 ae6e0db..60df95d 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
@@ -18,7 +18,13 @@ package org.apache.sis.internal.storage;
 
 import java.util.List;
 import java.util.Arrays;
+import java.util.Locale;
 import java.util.Optional;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.LogRecord;
+import java.util.concurrent.TimeUnit;
+import java.math.RoundingMode;
 import org.opengis.geometry.Envelope;
 import org.opengis.metadata.spatial.DimensionNameType;
 import org.opengis.referencing.operation.TransformException;
@@ -31,8 +37,15 @@ import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.SampleDimension;
 import org.apache.sis.storage.event.StoreListeners;
 import org.apache.sis.math.MathFunctions;
-import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.measure.Latitude;
+import org.apache.sis.measure.Longitude;
+import org.apache.sis.measure.AngleFormat;
 import org.apache.sis.util.ArraysExt;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.logging.PerformanceLevel;
+import org.apache.sis.internal.storage.io.IOUtilities;
+import org.apache.sis.internal.util.StandardDateFormat;
+import org.apache.sis.internal.jdk9.JDK9;
 
 
 /**
@@ -353,4 +366,57 @@ public abstract class AbstractGridResource extends AbstractResource implements
G
         }
         return null;
     }
+
+    /**
+     * Logs the execution of a {@link #read(GridGeometry, int...)} operation.
+     * The log level will be {@link Level#FINE} if the operation was quick enough,
+     * or {@link PerformanceLevel#SLOW} or higher level otherwise.
+     *
+     * @param  file        the file that was opened, or {@code null} for {@link #getSourceName()}.
+     * @param  domain      domain of the created grid coverage.
+     * @param  startTime   value of {@link System#nanoTime()} when the loading process started.
+     */
+    protected final void logReadOperation(final Object file, final GridGeometry domain, final
long startTime) {
+        final Logger logger = getLogger();
+        final long   nanos  = System.nanoTime() - startTime;
+        final Level  level  = PerformanceLevel.forDuration(nanos, TimeUnit.NANOSECONDS);
+        if (logger.isLoggable(level)) {
+            final Locale locale = getLocale();
+            final Object[] parameters = new Object[6];
+            parameters[0] = IOUtilities.filename(file != null ? file : getSourceName());
+            parameters[5] = nanos / (double) StandardDateFormat.NANOS_PER_SECOND;
+            JDK9.ifPresentOrElse(domain.getGeographicExtent(), (box) -> {
+                final AngleFormat f = new AngleFormat("D°MM′SS″", locale);
+                f.setRoundingMode(RoundingMode.FLOOR);
+                parameters[1] = f.format(new Latitude (box.getSouthBoundLatitude()));
+                parameters[3] = f.format(new Longitude(box.getWestBoundLongitude()));
+                f.setRoundingMode(RoundingMode.CEILING);
+                parameters[2] = f.format(new Latitude (box.getNorthBoundLatitude()));
+                parameters[4] = f.format(new Longitude(box.getEastBoundLongitude()));
+            }, () -> {
+                // If no geographic coordinates, fallback on the 2 first dimensions.
+                if (domain.isDefined(GridGeometry.ENVELOPE)) {
+                    final Envelope box = domain.getEnvelope();
+                    final int dimension = Math.min(box.getDimension(), 2);
+                    for (int t=1, i=0; i<dimension; i++) {
+                        parameters[t++] = box.getMinimum(i);
+                        parameters[t++] = box.getMaximum(i);
+                    }
+                } else if (domain.isDefined(GridGeometry.EXTENT)) {
+                    final GridExtent box = domain.getExtent();
+                    final int dimension = Math.min(box.getDimension(), 2);
+                    for (int t=1, i=0; i<dimension; i++) {
+                        parameters[t++] = box.getLow (i);
+                        parameters[t++] = box.getHigh(i);
+                    }
+                }
+            });
+            final LogRecord record = Resources.forLocale(locale)
+                    .getLogRecord(level, Resources.Keys.LoadedGridCoverage_6, parameters);
+            record.setSourceClassName(GridCoverageResource.class.getName());
+            record.setSourceMethodName("read");
+            record.setLoggerName(logger.getName());
+            logger.log(record);
+        }
+    }
 }
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java
index db98d42..e9e383b 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java
@@ -247,6 +247,11 @@ public final class Resources extends IndexedResourceBundle {
         public static final short InvalidSampleDimensionIndex_2 = 52;
 
         /**
+         * Loaded grid coverage between {1} – {2} and {3} – {4} from file “{0}” in
{5} seconds.
+         */
+        public static final short LoadedGridCoverage_6 = 59;
+
+        /**
          * Resource “{0}” does not have an identifier.
          */
         public static final short MissingResourceIdentifier_1 = 42;
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties
index 8def18a..84e8663 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties
@@ -56,6 +56,7 @@ IllegalInputTypeForReader_2       = The {0} reader does not accept inputs
of typ
 IllegalOutputTypeForWriter_2      = The {0} writer does not accept outputs of type \u2018{1}\u2019.
 InconsistentNameComponents_2      = Components of the \u201c{1}\u201d name are inconsistent
with those of the name previously binded in \u201c{0}\u201d data store.
 InvalidSampleDimensionIndex_2     = Sample dimension index {1} is invalid. Expected an index
from 0 to {0} inclusive.
+LoadedGridCoverage_6              = Loaded grid coverage between {1} \u2013 {2} and {3} \u2013
{4} from file \u201c{0}\u201d in {5} seconds.
 MissingResourceIdentifier_1       = Resource \u201c{0}\u201d does not have an identifier.
 MissingSchemeInURI_1              = Missing scheme in \u201c{0}\u201d URI.
 NoSuchResourceDirectory_1         = No directory of resources found at \u201c{0}\u201d.
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties
index 17b8672..dce1c2e 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties
@@ -61,6 +61,7 @@ IllegalInputTypeForReader_2       = Le lecteur {0} n\u2019accepte pas des
entr\u
 IllegalOutputTypeForWriter_2      = L\u2019encodeur {0} n\u2019accepte pas des sorties de
type \u2018{1}\u2019.
 InvalidSampleDimensionIndex_2     = L\u2019index de dimension d\u2019\u00e9chantillonnage
{1} est invalide. On attendait un index de 0 \u00e0 {0} inclusif.
 InconsistentNameComponents_2      = Les \u00e9l\u00e9ments qui composent le nom \u00ab\u202f{1}\u202f\u00bb
ne sont pas coh\u00e9rents avec ceux du nom qui avait \u00e9t\u00e9 pr\u00e9c\u00e9demment
li\u00e9 dans les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb.
+LoadedGridCoverage_6              = Lecture d\u2019une couverture de donn\u00e9es entre {1}
\u2013 {2} et {3} \u2013 {4} \u00e0 partir du fichier \u00ab\u202f{0}\u202f\u00bb en {5} secondes.
 MissingResourceIdentifier_1       = La ressource \u00ab\u202f{0}\u202f\u00bb n\u2019a pas
d\u2019identifiant.
 MissingSchemeInURI_1              = Il manque le sch\u00e9ma dans l\u2019URI \u00ab\u202f{0}\u202f\u00bb.
 NoSuchResourceDirectory_1         = Aucun r\u00e9pertoire de ressources n\u2019a \u00e9t\u00e9
trouv\u00e9 \u00e0 l\u2019emplacement \u00ab\u202f{0}\u202f\u00bb.
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java
index 3dd0f01..bbbd041 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java
@@ -20,6 +20,7 @@ import java.util.Set;
 import java.util.EnumSet;
 import java.util.Optional;
 import java.util.stream.Stream;
+import java.util.logging.Logger;
 import java.nio.file.OpenOption;
 import java.nio.file.StandardOpenOption;
 import java.nio.charset.Charset;
@@ -43,9 +44,11 @@ import org.apache.sis.storage.UnsupportedStorageException;
 import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.internal.jdk9.JDK9;
 import org.apache.sis.internal.metadata.Identifiers;
+import org.apache.sis.internal.system.Modules;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Classes;
+import org.apache.sis.util.logging.Logging;
 
 // Branch-dependent imports
 import org.opengis.feature.Feature;
@@ -63,6 +66,12 @@ import org.opengis.feature.Feature;
  */
 public final class StoreUtilities extends Static {
     /**
+     * Logger for the {@value Modules#STORAGE} module. This is used when no more specific
logger is available,
+     * or if the more specific logger is not appropriate (e.g. because the log message come
from base class).
+     */
+    public static final Logger LOGGER = Logging.getLogger(Modules.STORAGE);
+
+    /**
      * Names of encoding where bytes less than 128 can be interpreted as ASCII.
      *
      * @see #basedOnASCII(Charset)
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java
index 19fc4d3..4d04d9a 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java
@@ -37,7 +37,6 @@ import org.apache.sis.storage.event.StoreEvent;
 import org.apache.sis.storage.event.StoreListener;
 import org.apache.sis.storage.event.WarningEvent;
 import org.apache.sis.internal.storage.io.IOUtilities;
-import org.apache.sis.internal.system.Modules;
 import org.apache.sis.util.logging.Logging;
 
 
@@ -274,7 +273,7 @@ public abstract class URIDataStore extends DataStore implements StoreResource,
R
                  * Note that it does not mean the same thing than "parameter provided but
value is null".
                  * In that later case we want to return the null value as specified in the
parameters.
                  */
-                Logging.recoverableException(Logging.getLogger(Modules.STORAGE), URIDataStore.class,
"location", e);
+                Logging.recoverableException(StoreUtilities.LOGGER, URIDataStore.class, "location",
e);
             }
         }
         /*
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/FolderStoreProvider.java
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/FolderStoreProvider.java
index 461bf17..c630652 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/FolderStoreProvider.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/FolderStoreProvider.java
@@ -43,7 +43,6 @@ import org.apache.sis.storage.FeatureSet;
 import org.apache.sis.storage.GridCoverageResource;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.logging.Logging;
-import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.storage.Resources;
 import org.apache.sis.internal.storage.URIDataStore;
 import org.apache.sis.internal.storage.Capability;
@@ -164,7 +163,7 @@ public final class FolderStoreProvider extends DataStoreProvider {
                 return ProbeResult.SUPPORTED;
             }
         } catch (FileSystemNotFoundException e) {
-            Logging.recoverableException(Logging.getLogger(Modules.STORAGE), FolderStoreProvider.class,
"probeContent", e);
+            Logging.recoverableException(getLogger(), FolderStoreProvider.class, "probeContent",
e);
             // Nothing we can do, may happen often.
         }
         return ProbeResult.UNSUPPORTED_STORAGE;
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java
index 30d9ab7..e334cd6 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java
@@ -47,6 +47,7 @@ import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.storage.Resources;
+import org.apache.sis.internal.storage.StoreUtilities;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.ForwardOnlyStorageException;
 import org.apache.sis.storage.event.StoreListeners;
@@ -521,7 +522,7 @@ public abstract class ChannelFactory {
                 if (listeners != null) {
                     listeners.warning(record);
                 } else {
-                    Logging.getLogger(Modules.STORAGE).log(record);
+                    StoreUtilities.LOGGER.log(record);
                 }
             }
         }
@@ -548,6 +549,6 @@ public abstract class ChannelFactory {
      * the exception at {@link java.util.logging.Level#FINE} without stack trace.
      */
     private static void recoverableException(final Exception warning) {
-        Logging.recoverableException(Logging.getLogger(Modules.STORAGE), ChannelFactory.class,
"prepare", warning);
+        Logging.recoverableException(StoreUtilities.LOGGER, ChannelFactory.class, "prepare",
warning);
     }
 }
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
index 3e86208..d8b0cf2 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
@@ -336,9 +336,9 @@ public abstract class DataStoreProvider {
     }
 
     /**
-     * Returns the logger where to report warnings. This logger is used only if no
-     * {@link org.apache.sis.storage.event.StoreListener} has been registered for
-     * {@link org.apache.sis.storage.event.WarningEvent}.
+     * Returns the logger where to report warnings or loading operations.
+     * This logger is used only if no {@link org.apache.sis.storage.event.StoreListener}
+     * has been registered for {@link org.apache.sis.storage.event.WarningEvent}.
      *
      * <p>The default implementation returns a logger with the same name as the package
name
      * of the subclass of this {@code DataStoreProvider} instance. Subclasses should override
@@ -346,6 +346,8 @@ public abstract class DataStoreProvider {
      *
      * @return the logger to use as a fallback (when there is no listeners) for warning messages.
      *
+     * @see org.apache.sis.storage.event.StoreListeners#getLogger()
+     *
      * @since 1.0
      */
     public Logger getLogger() {
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
b/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
index 8f0521c..90bae45 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
@@ -49,13 +49,13 @@ import org.apache.sis.util.collection.TableColumn;
 import org.apache.sis.util.collection.DefaultTreeTable;
 import org.apache.sis.util.UnconvertibleObjectException;
 import org.apache.sis.internal.storage.Resources;
+import org.apache.sis.internal.storage.StoreUtilities;
 import org.apache.sis.internal.storage.io.IOUtilities;
 import org.apache.sis.internal.storage.io.ChannelFactory;
 import org.apache.sis.internal.storage.io.ChannelDataInput;
 import org.apache.sis.internal.storage.io.ChannelImageInputStream;
 import org.apache.sis.internal.storage.io.InputStreamAdapter;
 import org.apache.sis.internal.storage.io.RewindableLineReader;
-import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.util.Strings;
 import org.apache.sis.io.InvalidSeekException;
 import org.apache.sis.setup.OptionKey;
@@ -826,7 +826,7 @@ public class StorageConnector implements Serializable {
                 view = ObjectConverters.convert(storage, type);
             } catch (UnconvertibleObjectException e) {
                 if (!OPENERS.containsKey(type)) throw e;
-                Logging.recoverableException(Logging.getLogger(Modules.STORAGE), StorageConnector.class,
"getStorageAs", e);
+                Logging.recoverableException(StoreUtilities.LOGGER, StorageConnector.class,
"getStorageAs", e);
                 view = null;
             }
             addView(type, view);
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/event/StoreListeners.java
b/storage/sis-storage/src/main/java/org/apache/sis/storage/event/StoreListeners.java
index b5bd5c7..8c0819a 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/storage/event/StoreListeners.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/event/StoreListeners.java
@@ -29,8 +29,8 @@ import org.apache.sis.util.Exceptions;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Vocabulary;
-import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.storage.StoreResource;
+import org.apache.sis.internal.storage.StoreUtilities;
 import org.apache.sis.storage.DataStoreProvider;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.Resource;
@@ -315,8 +315,12 @@ public class StoreListeners implements Localized {
      * </ul>
      *
      * @return the logger where to send the warnings when there is no other destination.
+     *
+     * @see DataStoreProvider#getLogger()
+     *
+     * @since 1.1
      */
-    private Logger getLogger() {
+    public Logger getLogger() {
         Resource src = source;
         final DataStore ds = getDataStore(this);
         if (ds != null) {
@@ -423,7 +427,7 @@ public class StoreListeners implements Localized {
                 }
             }
         } catch (ClassNotFoundException | SecurityException e) {
-            Logging.ignorableException(Logging.getLogger(Modules.STORAGE), StoreListeners.class,
"warning", e);
+            Logging.ignorableException(StoreUtilities.LOGGER, StoreListeners.class, "warning",
e);
         }
         warning(record);
     }


Mime
View raw message