You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2023/02/09 13:57:15 UTC

[sis] branch geoapi-4.0 updated (420b428372 -> f96f7ad0f8)

This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a change to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


    from 420b428372 Documentation about assertions.
     new 609d7f75da Documentation about static methods.
     new 6dbf748b40 Replace calls to `Paths.get(…)` by calls to `Path.of(…)`. According Javadoc, `Paths` may be deprecated in a future Java version.
     new f96f7ad0f8 When the `InputStream` to wrap in a `ChannelDataInput` is backed by an array, wrap the underlying array (in read-only mode) instead of copying it.

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../org/apache/sis/console/MimeTypeCommand.java    |   4 +-
 .../apache/sis/internal/gui/DataStoreOpener.java   |   3 +-
 .../org/apache/sis/internal/setup/FXFinder.java    |   5 +-
 .../org/apache/sis/internal/doclet/Doclet.java     |   3 +-
 .../org/apache/sis/internal/doclet/Taglet.java     |   3 +-
 .../org/apache/sis/internal/unopkg/JavaMaker.java  |   5 +-
 .../sis/internal/metadata/sql/LocalDataSource.java |   7 +-
 .../org/apache/sis/metadata/sql/Citations.sql      |   2 +-
 .../sis/metadata/iso/citation/CitationsTest.java   |   2 +-
 .../sis/metadata/sql/MetadataSourceTest.java       |   2 +-
 .../org/apache/sis/xml/RenameListGenerator.java    |   6 +-
 .../referencing/PositionalAccuracyConstant.java    |   2 +-
 .../referencing/provider/DatumShiftGridLoader.java |   3 +-
 .../java/org/apache/sis/io/wkt/WKTDictionary.java  |   2 +-
 .../internal/referencing/provider/NTv2Test.java    |   3 +-
 .../factory/sql/epsg/DataScriptFormatter.java      |   3 +-
 .../sis/internal/converter/PathConverter.java      |   5 +-
 .../sis/internal/converter/StringConverter.java    |   2 +-
 .../apache/sis/internal/system/DataDirectory.java  |   3 +-
 .../org/apache/sis/internal/util/DoubleDouble.java |   2 +-
 .../src/main/java/org/apache/sis/io/IO.java        |   2 +-
 .../src/main/java/org/apache/sis/util/Static.java  | 100 +++++++--------
 .../org/apache/sis/util/logging/Initializer.java   |   3 +-
 .../internal/converter/StringConverterTest.java    |   3 +-
 .../org/apache/sis/test/ProjectDirectories.java    |   3 +-
 .../java/org/apache/sis/storage/landsat/Band.java  |   3 +-
 .../sis/storage/landsat/LandsatStoreProvider.java  |   3 +-
 .../sis/internal/sql/postgis/RasterReader.java     |  14 ++-
 .../apache/sis/internal/storage/URIDataStore.java  |   3 +-
 .../sis/internal/storage/io/ChannelDataInput.java  |  27 +++--
 .../sis/internal/storage/io/ChannelFactory.java    |   3 +-
 .../sis/internal/storage/io/IOUtilities.java       |  16 +--
 .../storage/io/InputStreamArrayGetter.java         | 135 +++++++++++++++++++++
 .../sis/internal/storage/folder/StoreTest.java     |   3 +-
 .../storage/io/InputStreamArrayGetterTest.java     |  62 ++++++++++
 .../apache/sis/test/suite/StorageTestSuite.java    |   1 +
 36 files changed, 319 insertions(+), 129 deletions(-)
 create mode 100644 storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/InputStreamArrayGetter.java
 create mode 100644 storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/InputStreamArrayGetterTest.java


[sis] 01/03: Documentation about static methods.

Posted by de...@apache.org.
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 609d7f75da94c0da1ddab8568116cf8896de49bf
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Thu Feb 9 10:34:07 2023 +0100

    Documentation about static methods.
---
 .../org/apache/sis/metadata/sql/Citations.sql      |   2 +-
 .../sis/metadata/iso/citation/CitationsTest.java   |   2 +-
 .../sis/metadata/sql/MetadataSourceTest.java       |   2 +-
 .../referencing/PositionalAccuracyConstant.java    |   2 +-
 .../org/apache/sis/internal/util/DoubleDouble.java |   2 +-
 .../src/main/java/org/apache/sis/io/IO.java        |   2 +-
 .../src/main/java/org/apache/sis/util/Static.java  | 100 +++++++++++----------
 .../sis/internal/storage/io/IOUtilities.java       |   5 +-
 8 files changed, 62 insertions(+), 55 deletions(-)

diff --git a/core/sis-metadata/src/main/resources/org/apache/sis/metadata/sql/Citations.sql b/core/sis-metadata/src/main/resources/org/apache/sis/metadata/sql/Citations.sql
index a6d7c9ab69..2d0626052e 100644
--- a/core/sis-metadata/src/main/resources/org/apache/sis/metadata/sql/Citations.sql
+++ b/core/sis-metadata/src/main/resources/org/apache/sis/metadata/sql/Citations.sql
@@ -4,7 +4,7 @@
 --
 
 --
--- This script creates some tables needed for SIS pre-defined Citation constants.
+-- This script creates some tables needed for SIS predefined Citation constants.
 -- We do not need to create all tables or all table columns here; missing tables
 -- and columns will be added on-the-fly by SIS as needed. Enumeration values are
 -- replaced by VARCHAR on databases that do not support the ENUM type.
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/CitationsTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/CitationsTest.java
index dbd8b6da7d..ff10ed037c 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/CitationsTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/CitationsTest.java
@@ -256,7 +256,7 @@ public final class CitationsTest extends TestCase {
         assertNotNull(identifiers);
         try {
             identifiers.add(null);
-            fail("Pre-defined metadata shall be unmodifiable.");
+            fail("Predefined metadata shall be unmodifiable.");
         } catch (UnsupportedOperationException e) {
             // This is the expected exception.
         }
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataSourceTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataSourceTest.java
index 199df45513..b7ba03d295 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataSourceTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataSourceTest.java
@@ -165,7 +165,7 @@ public final class MetadataSourceTest extends TestCase {
         final InternationalString more = new SimpleInternationalString("An open source project.");
         try {
             titles.add(more);
-            fail("Pre-defined metadata should be unmodifiable.");
+            fail("Predefined metadata should be unmodifiable.");
         } catch (UnsupportedOperationException e) {
             // This is the expected exception.
         }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java
index 246bdfb7ab..6d28f93f21 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java
@@ -41,7 +41,7 @@ import org.apache.sis.util.resources.Vocabulary;
 
 
 /**
- * Pre-defined positional accuracy resulting from some coordinate operations.
+ * Predefined positional accuracy resulting from some coordinate operations.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 1.1
diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java b/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
index f3a0f85679..a9a5063e85 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
@@ -91,7 +91,7 @@ public final class DoubleDouble extends Number implements Comparable<DoubleDoubl
     private static final int ZERO_THRESHOLD = 2;
 
     /**
-     * Pre-defined constants frequently used in SIS, sorted in increasing order. This table contains only
+     * Predefined constants frequently used in SIS, sorted in increasing order. This table contains only
      * constants that cannot be inferred by {@link DecimalFunctions#deltaForDoubleToDecimal(double)},
      * for example some transcendental values.
      *
diff --git a/core/sis-utility/src/main/java/org/apache/sis/io/IO.java b/core/sis-utility/src/main/java/org/apache/sis/io/IO.java
index 736aa2d2d0..b4a36aeb7b 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/io/IO.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/io/IO.java
@@ -27,7 +27,7 @@ import org.apache.sis.util.resources.Vocabulary;
 
 
 /**
- * Utilities methods working on {@link java.io} objects.
+ * Utilities methods working on {@link Appendable} objects.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 0.3
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/Static.java b/core/sis-utility/src/main/java/org/apache/sis/util/Static.java
index 01ca58fb69..29cdbeefe7 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/Static.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/Static.java
@@ -18,71 +18,79 @@ package org.apache.sis.util;
 
 
 /**
- * Parent of SIS classes that contain only static utility methods, for documentation purpose.
+ * Parent of SIS classes that contain only static utility methods.
+ * This parent class is used for documentation purpose only.
  * The list below summarizes some of the utility classes:
  *
  * <table class="sis">
  * <caption>Static utility classes (non exhaustive list)</caption>
- * <tr><th colspan="2">Classes of the Java language</th></tr>
- * <tr><td>{@link Characters}</td>
- *     <td>Find subscript and superscript digit characters.</td></tr>
- * <tr><td>{@link CharSequences}</td>
- *     <td>Methods working on {@link CharSequence} or {@link String} instances.</td></tr>
- * <tr><td>{@link StringBuilders}</td>
- *     <td>Methods modifying {@link StringBuilder} content in-place.</td></tr>
- * <tr><td>{@link Numbers}</td>
- *     <td>Methods working with {@link Number} instances (include conversions between different types).</td></tr>
- * <tr><td>{@link Classes}</td>
- *     <td>Methods working with {@link Class} instances.</td></tr>
- * <tr><td>{@link org.apache.sis.util.collection.Containers}</td>
- *     <td>Additions to the JDK {@link java.util.Collections} methods, also related to the
- *         {@link org.apache.sis.util.collection.CheckedContainer} interface.</td></tr>
- * <tr><td>{@link ArraysExt}</td>
- *     <td>Additions to the JDK {@link java.util.Arrays} methods
- *         (include insert or remove of elements in the middle of arrays).</td></tr>
- *
- * <tr><th colspan="2" class="hsep">Mathematics and units of measurement</th></tr>
- * <tr><td>{@link org.apache.sis.math.MathFunctions}</td>
- *     <td>Additions to the {@link java.lang.Math} methods.</td></tr>
- * <tr><td>{@link org.apache.sis.math.DecimalFunctions}</td>
- *     <td>Mathematical methods related to base 10 representation of numbers.</td></tr>
- * <tr><td>{@link org.apache.sis.referencing.operation.matrix.Matrices}</td>
- *     <td>Create and compare {@link org.opengis.referencing.operation.Matrix} objects</td></tr>
- * <tr><td>{@link org.apache.sis.measure.Units}</td>
- *     <td>Get a {@linkplain javax.measure.Unit unit} from a symbol or EPSG code,
- *         and test if a unit is angular, linear or temporal.</td></tr>
- *
  * <tr><th colspan="2" class="hsep">OGC/ISO objects (metadata, referencing, geometries)</th></tr>
- * <tr><td>{@link org.apache.sis.util.iso.Types}</td>
- *     <td>UML identifier and description for GeoAPI types.</td></tr>
- * <tr><td>{@link org.apache.sis.util.iso.Names}</td>
- *     <td>Simple creation and operations on {@link org.opengis.util.GenericName} objects.</td></tr>
  * <tr><td>{@link org.apache.sis.metadata.iso.citation.Citations}</td>
- *     <td>Pre-defined {@link org.opengis.metadata.citation.Citation}
+ *     <td>Predefined {@link org.opengis.metadata.citation.Citation}
  *         and methods for comparing against titles or identifiers.</td></tr>
- * <tr><td>{@link org.apache.sis.metadata.iso.extent.Extents}</td>
- *     <td>Extract information from {@link org.opengis.metadata.extent.Extent} objects.</td></tr>
+ * <tr><td>{@link org.apache.sis.referencing.cs.CoordinateSystems}</td>
+ *     <td>Parses axis names and creates transforms between {@link org.opengis.referencing.cs.CoordinateSystem}
+ *         instances.</td></tr>
+ * <tr><td>{@link org.apache.sis.referencing.CRS}</td>
+ *     <td>Instantiates or provides information about {@link org.opengis.referencing.crs.CoordinateReferenceSystem}.</td></tr>
  * <tr><td>{@link org.apache.sis.geometry.Envelopes}</td>
  *     <td>Parse, format and transform {@link org.opengis.geometry.Envelope} objects.</td></tr>
+ * <tr><td>{@link org.apache.sis.metadata.iso.extent.Extents}</td>
+ *     <td>Extract information from {@link org.opengis.metadata.extent.Extent} objects.</td></tr>
  * <tr><td>{@link org.apache.sis.referencing.IdentifiedObjects}</td>
  *     <td>Handle names, identifiers or properties of
  *         {@link org.opengis.referencing.IdentifiedObject} instances.</td></tr>
- * <tr><td>{@link org.apache.sis.referencing.cs.CoordinateSystems}</td>
- *     <td>Parses axis names and creates transforms between {@link org.opengis.referencing.cs.CoordinateSystem}
- *         instances.</td></tr>
+ * <tr><td>{@link org.apache.sis.util.iso.Names}</td>
+ *     <td>Simple creation and operations on {@link org.opengis.util.GenericName} objects.</td></tr>
  * <tr><td>{@link org.apache.sis.parameter.Parameters}</td>
  *     <td>Creates, searches or modifies {@link org.opengis.parameter.ParameterValue} instances
  *         in a group of parameters.</td></tr>
+ * <tr><td>{@link org.apache.sis.util.iso.Types}</td>
+ *     <td>UML identifier and description for GeoAPI types.</td></tr>
+ *
+ * <tr><th colspan="2" class="hsep">Mathematics and units of measurement</th></tr>
+ * <tr><td>{@link org.apache.sis.math.DecimalFunctions}</td>
+ *     <td>Mathematical methods related to base 10 representation of numbers.</td></tr>
+ * <tr><td>{@link org.apache.sis.math.MathFunctions}</td>
+ *     <td>Additions to the {@link java.lang.Math} methods.</td></tr>
+ * <tr><td>{@link org.apache.sis.referencing.operation.matrix.Matrices}</td>
+ *     <td>Create and compare {@link org.opengis.referencing.operation.Matrix} objects</td></tr>
+ * <tr><td>{@link org.apache.sis.measure.Quantities}</td>
+ *     <td>Operations on {@linkplain javax.measure.Quantity quantities}
+ *         (values with units of measurement).</td></tr>
+ * <tr><td>{@link org.apache.sis.measure.Units}</td>
+ *     <td>Get a {@linkplain javax.measure.Unit unit} from a symbol or EPSG code,
+ *         and test if a unit is angular, linear or temporal.</td></tr>
  *
  * <tr><th colspan="2" class="hsep">Input / Output (including CRS, XML, images)</th></tr>
- * <tr><td>{@link org.apache.sis.io.IO}</td>
- *     <td>Methods working on {@link Appendable} instances.</td></tr>
  * <tr><td>{@link org.apache.sis.storage.DataStores}</td>
  *     <td>Read or write geospatial data in various backends.</td></tr>
- * <tr><td>{@link org.apache.sis.xml.XML}</td>
- *     <td>Marshal or unmarshal ISO 19115 objects.</td></tr>
+ * <tr><td>{@link org.apache.sis.io.IO}</td>
+ *     <td>Methods working on {@link Appendable} instances.</td></tr>
  * <tr><td>{@link org.apache.sis.xml.Namespaces}</td>
  *     <td>{@code String} constants for commonly used namespaces.</td></tr>
+ * <tr><td>{@link org.apache.sis.xml.XML}</td>
+ *     <td>Marshal or unmarshal ISO 19115 objects.</td></tr>
+ *
+ * <tr><th colspan="2">Miscellaneous utilities</th></tr>
+ * <tr><td>{@link ArraysExt}</td>
+ *     <td>Additions to the JDK {@link java.util.Arrays} methods
+ *         (include insert or remove of elements in the middle of arrays).</td></tr>
+ * <tr><td>{@link Characters}</td>
+ *     <td>Find subscript and superscript digit characters.</td></tr>
+ * <tr><td>{@link CharSequences}</td>
+ *     <td>Methods working on {@link CharSequence} or {@link String} instances.</td></tr>
+ * <tr><td>{@link Classes}</td>
+ *     <td>Methods working with {@link Class} instances.</td></tr>
+ * <tr><td>{@link org.apache.sis.util.collection.Containers}</td>
+ *     <td>Additions to the JDK {@link java.util.Collections} methods, also related to the
+ *         {@link org.apache.sis.util.collection.CheckedContainer} interface.</td></tr>
+ * <tr><td>{@link Numbers}</td>
+ *     <td>Methods working with {@link Number} instances (include conversions between different types).</td></tr>
+ * <tr><td>{@link ObjectConverters}</td>
+ *     <td>Create {@link ObjectConverter} instances, or collection views using object converters.</td></tr>
+ * <tr><td>{@link StringBuilders}</td>
+ *     <td>Methods modifying {@link StringBuilder} content in-place.</td></tr>
  *
  * <tr><th colspan="2" class="hsep">Loggings and exceptions</th></tr>
  * <tr><td>{@link ArgumentChecks}</td>
@@ -92,10 +100,6 @@ package org.apache.sis.util;
  * <tr><td>{@link org.apache.sis.util.logging.Logging}</td>
  *     <td>Get a JDK {@linkplain java.util.logging.Logger logger}, which may be a wrapper around
  *         the <cite>Apache Commons Logging</cite> or <cite>Log4J</cite> framework.</td></tr>
- *
- * <tr><th colspan="2" class="hsep">Factories</th></tr>
- * <tr><td>{@link ObjectConverters}</td>
- *     <td>Create {@link ObjectConverter} instances, or collection views using object converters.</td></tr>
  * </table>
  *
  * @author  Martin Desruisseaux (Geomatys)
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java
index 7e4ca240b6..e11700a9bf 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java
@@ -61,7 +61,10 @@ import org.apache.sis.internal.storage.Resources;
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Johann Sorel (Geomatys)
  * @version 1.4
- * @since   0.3
+ *
+ * @see org.apache.sis.io.IO
+ *
+ * @since 0.3
  */
 public final class IOUtilities extends Static {
     /**


[sis] 02/03: Replace calls to `Paths.get(…)` by calls to `Path.of(…)`. According Javadoc, `Paths` may be deprecated in a future Java version.

Posted by de...@apache.org.
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 6dbf748b406ee9317898441f9c454248b5f22a4b
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Thu Feb 9 10:56:25 2023 +0100

    Replace calls to `Paths.get(…)` by calls to `Path.of(…)`.
    According Javadoc, `Paths` may be deprecated in a future Java version.
---
 .../src/main/java/org/apache/sis/console/MimeTypeCommand.java |  4 ++--
 .../java/org/apache/sis/internal/gui/DataStoreOpener.java     |  3 +--
 .../src/main/java/org/apache/sis/internal/setup/FXFinder.java |  5 ++---
 .../src/main/java/org/apache/sis/internal/doclet/Doclet.java  |  3 +--
 .../src/main/java/org/apache/sis/internal/doclet/Taglet.java  |  3 +--
 .../main/java/org/apache/sis/internal/unopkg/JavaMaker.java   |  5 ++---
 .../org/apache/sis/internal/metadata/sql/LocalDataSource.java |  7 +++----
 .../src/test/java/org/apache/sis/xml/RenameListGenerator.java |  6 +++---
 .../internal/referencing/provider/DatumShiftGridLoader.java   |  3 +--
 .../src/main/java/org/apache/sis/io/wkt/WKTDictionary.java    |  2 +-
 .../apache/sis/internal/referencing/provider/NTv2Test.java    |  3 +--
 .../sis/referencing/factory/sql/epsg/DataScriptFormatter.java |  3 +--
 .../java/org/apache/sis/internal/converter/PathConverter.java |  5 ++---
 .../org/apache/sis/internal/converter/StringConverter.java    |  2 +-
 .../java/org/apache/sis/internal/system/DataDirectory.java    |  3 +--
 .../main/java/org/apache/sis/util/logging/Initializer.java    |  3 +--
 .../apache/sis/internal/converter/StringConverterTest.java    |  3 +--
 .../src/test/java/org/apache/sis/test/ProjectDirectories.java |  3 +--
 .../src/main/java/org/apache/sis/storage/landsat/Band.java    |  3 +--
 .../org/apache/sis/storage/landsat/LandsatStoreProvider.java  |  3 +--
 .../java/org/apache/sis/internal/storage/URIDataStore.java    |  3 +--
 .../org/apache/sis/internal/storage/io/ChannelFactory.java    |  3 +--
 .../java/org/apache/sis/internal/storage/io/IOUtilities.java  | 11 +++++------
 .../org/apache/sis/internal/storage/folder/StoreTest.java     |  3 +--
 24 files changed, 36 insertions(+), 56 deletions(-)

diff --git a/application/sis-console/src/main/java/org/apache/sis/console/MimeTypeCommand.java b/application/sis-console/src/main/java/org/apache/sis/console/MimeTypeCommand.java
index 3c4f572f41..06ec5db9b5 100644
--- a/application/sis-console/src/main/java/org/apache/sis/console/MimeTypeCommand.java
+++ b/application/sis-console/src/main/java/org/apache/sis/console/MimeTypeCommand.java
@@ -20,7 +20,7 @@ import java.net.URI;
 import java.util.EnumSet;
 import java.net.URISyntaxException;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.nio.file.NoSuchFileException;
 import java.nio.file.FileSystemNotFoundException;
 import org.apache.sis.storage.DataStores;
@@ -97,7 +97,7 @@ final class MimeTypeCommand extends CommandRunner {
                  */
                 type = DataStores.probeContentType(file);
             } else try {
-                type = Files.probeContentType(Paths.get(uri));
+                type = Files.probeContentType(Path.of(uri));
             } catch (IllegalArgumentException | FileSystemNotFoundException e) {
                 type = DataStores.probeContentType(uri);
             } catch (NoSuchFileException e) {
diff --git a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/DataStoreOpener.java b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/DataStoreOpener.java
index 20fed85abd..84e41c114e 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/DataStoreOpener.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/DataStoreOpener.java
@@ -20,7 +20,6 @@ import java.net.URI;
 import java.net.URL;
 import java.io.File;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.util.Locale;
@@ -135,7 +134,7 @@ public final class DataStoreOpener extends Task<DataStore> {
                     source = ((URL) source).toURI();                // May throw URISyntaxException.
                 }
                 if (source instanceof URI) {                        // May be the result of above URL.toURI().
-                    source = Paths.get((URI) source);               // May throw FileSystemNotFoundException.
+                    source = Path.of((URI) source);                 // May throw FileSystemNotFoundException.
                 }
                 if (source instanceof Path) {                       // May be the result of a previous block.
                     source = ((Path) source).toRealPath();          // May throw IOException.
diff --git a/application/sis-javafx/src/main/java/org/apache/sis/internal/setup/FXFinder.java b/application/sis-javafx/src/main/java/org/apache/sis/internal/setup/FXFinder.java
index 5073b63eea..a8e120d037 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/internal/setup/FXFinder.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/internal/setup/FXFinder.java
@@ -21,7 +21,6 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
 import java.util.Enumeration;
@@ -137,7 +136,7 @@ public final class FXFinder {
      * Creates a new finder.
      */
     private FXFinder(final String setenv) {
-        this.setenv = Paths.get(setenv).normalize();
+        this.setenv = Path.of(setenv).normalize();
         isWindows = setenv.endsWith(WINDOWS_BATCH_EXTENSION);
     }
 
@@ -203,7 +202,7 @@ public final class FXFinder {
             } else if (value.isEmpty()) {
                 value = "(blank)";
             } else if (name.equals("SIS_DATA") && value.equals("bin/../data")) {
-                value = Paths.get(value).toAbsolutePath().toString();
+                value = Path.of(value).toAbsolutePath().toString();
             }
         } catch (SecurityException e) {
             value  = "(unreadable)";
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Doclet.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Doclet.java
index 08dbea6280..e7c77981e7 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Doclet.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Doclet.java
@@ -20,7 +20,6 @@ import java.util.Set;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.UncheckedIOException;
@@ -112,7 +111,7 @@ public final class Doclet extends StandardDoclet {
     public boolean run(final DocletEnvironment environment) {
         final boolean success = super.run(environment);
         if (success && outputDirectory != null) try {
-            final Path output = Paths.get(outputDirectory);
+            final Path output = Path.of(outputDirectory);
             final Path resources = resources(output);
             copyResources(resources, output);
             final Rewriter r = new Rewriter();
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Taglet.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Taglet.java
index 707ab08927..acb188f712 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Taglet.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Taglet.java
@@ -20,7 +20,6 @@ import java.util.Set;
 import java.util.EnumSet;
 import java.util.List;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import javax.tools.Diagnostic;
 import javax.lang.model.element.Element;
 import jdk.javadoc.doclet.DocletEnvironment;
@@ -120,7 +119,7 @@ abstract class Taglet implements jdk.javadoc.doclet.Taglet {
             final TreePath path = trees.getPath(element);
             if (path != null) {
                 // Following methods do not document 'null' as a possible return value.
-                return Paths.get(path.getCompilationUnit().getSourceFile().toUri());
+                return Path.of(path.getCompilationUnit().getSourceFile().toUri());
             }
         }
         return null;
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/JavaMaker.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/JavaMaker.java
index ecb6c7a89e..7fd86e08a8 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/JavaMaker.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/JavaMaker.java
@@ -18,7 +18,6 @@ package org.apache.sis.internal.unopkg;
 
 import java.io.IOException;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.Files;
 import java.nio.file.FileVisitResult;
 import java.nio.file.SimpleFileVisitor;
@@ -107,8 +106,8 @@ public final class JavaMaker extends AbstractMojo {
          * @param outputDirectory  directory where the output Java files will be located.
          */
         Copier(final String baseDirectory, final String outputDirectory) {
-            source = Paths.get(baseDirectory).resolve(UnoPkg.SOURCE_DIRECTORY);
-            target = Paths.get(outputDirectory);
+            source = Path.of(baseDirectory).resolve(UnoPkg.SOURCE_DIRECTORY);
+            target = Path.of(outputDirectory);
         }
 
         /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/LocalDataSource.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/LocalDataSource.java
index f464f003eb..1897e5b6d7 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/LocalDataSource.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/LocalDataSource.java
@@ -26,7 +26,6 @@ import java.io.PrintWriter;
 import java.lang.reflect.Method;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.LogRecord;
@@ -129,7 +128,7 @@ public final class LocalDataSource implements DataSource, Comparable<LocalDataSo
                  */
                 Path path = dir.resolve(database);
                 if (home != null) try {
-                    path = Paths.get(home).relativize(path);
+                    path = Path.of(home).relativize(path);
                 } catch (IllegalArgumentException | SecurityException e) {
                     // The path cannot be relativized. This is okay.
                     Logging.recoverableException(LOGGER, LocalDataSource.class, "<init>", e);
@@ -137,7 +136,7 @@ public final class LocalDataSource implements DataSource, Comparable<LocalDataSo
                 path   = path.normalize();
                 dbFile = path.toString().replace(path.getFileSystem().getSeparator(), "/");
                 switch (dialect) {
-                    case HSQL: path = Paths.get(path.toString() + ".data"); break;
+                    case HSQL: path = Path.of(path.toString() + ".data"); break;
                     // More cases may be added in the future.
                 }
                 create = !Files.exists(path);
@@ -148,7 +147,7 @@ public final class LocalDataSource implements DataSource, Comparable<LocalDataSo
                  * if the database does not exist in that directory, because otherwise users could define
                  * SIS_DATA and get the impression that their setting is ignored.
                  */
-                final Path path = Paths.get(home);
+                final Path path = Path.of(home);
                 create = !Files.exists(path.resolve(database)) && Files.isDirectory(path);
                 dbFile = database;
             } else {
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/xml/RenameListGenerator.java b/core/sis-metadata/src/test/java/org/apache/sis/xml/RenameListGenerator.java
index c90fb51de6..64b0e65e91 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/xml/RenameListGenerator.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/xml/RenameListGenerator.java
@@ -63,9 +63,9 @@ import org.apache.sis.internal.xml.LegacyNamespaces;
  *
  * {@snippet lang="java" :
  *     public static void main(String[] args) throws Exception {
- *         RenameListGenerator gen = new RenameListGenerator(Paths.get("/home/user/project/build/classes"));
- *         gen.add(Paths.get("org/apache/sis/metadata/iso"));
- *         try (final BufferedWriter out = Files.newBufferedWriter(Paths.get("MyOutputFile.lst"))) {
+ *         RenameListGenerator gen = new RenameListGenerator(Path.of("/home/user/project/build/classes"));
+ *         gen.add(Path.of("org/apache/sis/metadata/iso"));
+ *         try (final BufferedWriter out = Files.newBufferedWriter(Path.of("MyOutputFile.lst"))) {
  *             gen.print(out);
  *         }
  *     }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java
index ee7e0e31d7..8f7e7919b2 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java
@@ -24,7 +24,6 @@ import java.io.IOException;
 import java.net.URI;
 import java.nio.ByteBuffer;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.Files;
 import java.nio.file.NoSuchFileException;
 import java.nio.file.FileSystemNotFoundException;
@@ -191,7 +190,7 @@ abstract class DatumShiftGridLoader {
      */
     static ReadableByteChannel newByteChannel(final URI path) throws IOException {
         try {
-            return Files.newByteChannel(Paths.get(path));
+            return Files.newByteChannel(Path.of(path));
         } catch (FileSystemNotFoundException e) {
             Logging.ignorableException(AbstractProvider.LOGGER, DatumShiftGridLoader.class, "newByteChannel", e);
         }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/WKTDictionary.java b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/WKTDictionary.java
index 17b4eb2193..0a94ea1f56 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/WKTDictionary.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/WKTDictionary.java
@@ -92,7 +92,7 @@ import org.apache.sis.util.SimpleInternationalString;
  *     public final class MyCRS extends WKTDictionary implements CRSAuthorityFactory {
  *         MyCRS() throws IOException, FactoryException {
  *             super(new DefaultCitation("MyAuthority"));
- *             try (BufferedReader source = Files.newBufferedReader(Paths.get("MyCRS.txt"))) {
+ *             try (BufferedReader source = Files.newBufferedReader(Path.of("MyCRS.txt"))) {
  *                 load(source);
  *             }
  *         }
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NTv2Test.java b/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NTv2Test.java
index 2248734b4f..d40f0202fb 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NTv2Test.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NTv2Test.java
@@ -21,7 +21,6 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.Files;
 import java.nio.file.StandardOpenOption;
 import java.nio.channels.WritableByteChannel;
@@ -179,7 +178,7 @@ public final class NTv2Test extends DatumShiftTestCase {
         assumeTrue(RUN_EXTENSIVE_TESTS);
         assumeTrue(DataDirectory.getenv() != null);
         final URI file = DatumShiftGridLoader.toAbsolutePath(new URI(MULTIGRID_TEST_FILE));
-        assumeTrue(Files.exists(Paths.get(file)));
+        assumeTrue(Files.exists(Path.of(file)));
         final DatumShiftGridFile<Angle,Angle> grid = NTv2.getOrLoad(NTv2.class, file, 2);
         assertInstanceOf("Should contain many grids.", DatumShiftGridGroup.class, grid);
         assertEquals("coordinateUnit",  Units.ARC_SECOND, grid.getCoordinateUnit());
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/epsg/DataScriptFormatter.java b/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/epsg/DataScriptFormatter.java
index 881c63b6df..fe5226526c 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/epsg/DataScriptFormatter.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/epsg/DataScriptFormatter.java
@@ -24,7 +24,6 @@ import java.io.InputStreamReader;
 import java.io.Writer;
 import java.io.IOException;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.Files;
 import java.nio.charset.StandardCharsets;
 import java.sql.Connection;
@@ -75,7 +74,7 @@ public final class DataScriptFormatter extends ScriptRunner {
              Connection c = db.source.getConnection())
         {
             final DataScriptFormatter f = new DataScriptFormatter(c);
-            f.run(Paths.get(arguments[0]), Paths.get(arguments[1]));
+            f.run(Path.of(arguments[0]), Path.of(arguments[1]));
         }
     }
 
diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/converter/PathConverter.java b/core/sis-utility/src/main/java/org/apache/sis/internal/converter/PathConverter.java
index e02fa427c6..e1cc71d8b1 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/internal/converter/PathConverter.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/internal/converter/PathConverter.java
@@ -20,7 +20,6 @@ import java.util.Set;
 import java.util.EnumSet;
 import java.io.File;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.net.URL;
 import java.net.URI;
 import java.net.MalformedURLException;
@@ -194,7 +193,7 @@ abstract class PathConverter<S,T> extends SystemConverter<S,T> {
         @Override public ObjectConverter<URL,Path> unique()  {return INSTANCE;}
         @Override public ObjectConverter<Path,URL> inverse() {return PathURL.INSTANCE;}
         @Override public Path doConvert(final URL source) throws URISyntaxException {
-            return Paths.get(source.toURI());
+            return Path.of(source.toURI());
         }
     }
 
@@ -209,7 +208,7 @@ abstract class PathConverter<S,T> extends SystemConverter<S,T> {
         @Override public ObjectConverter<URI,Path> unique()  {return INSTANCE;}
         @Override public ObjectConverter<Path,URI> inverse() {return PathURI.INSTANCE;}
         @Override public Path doConvert(final URI source) throws IllegalArgumentException {
-            return Paths.get(source);
+            return Path.of(source);
         }
     }
 
diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/converter/StringConverter.java b/core/sis-utility/src/main/java/org/apache/sis/internal/converter/StringConverter.java
index 4fe9b79381..142629c27c 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/internal/converter/StringConverter.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/internal/converter/StringConverter.java
@@ -279,7 +279,7 @@ abstract class StringConverter<T> extends SystemConverter<String, T> {
         public Path() {super(java.nio.file.Path.class);}                            // Instantiated by ServiceLoader.
 
         @Override java.nio.file.Path doConvert(String source) throws InvalidPathException {
-            return java.nio.file.Paths.get(source);
+            return java.nio.file.Path.of(source);
         }
     }
 
diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java b/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java
index ceafacb194..c1302ab53a 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java
@@ -19,7 +19,6 @@ package org.apache.sis.internal.system;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.InvalidPathException;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
@@ -171,7 +170,7 @@ public enum DataDirectory {
             if (dir == null || dir.isEmpty()) {
                 warning(null, Messages.Keys.DataDirectoryNotSpecified_1, ENV);
             } else try {
-                final Path path = Paths.get(dir);
+                final Path path = Path.of(dir);
                 if (!Files.isDirectory(path)) {
                     warning(null, Messages.Keys.DataDirectoryDoesNotExist_2, ENV, path);
                 } else if (!Files.isReadable(path)) {
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/logging/Initializer.java b/core/sis-utility/src/main/java/org/apache/sis/util/logging/Initializer.java
index 004fe465a1..b9fc17efa9 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/logging/Initializer.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/logging/Initializer.java
@@ -24,7 +24,6 @@ import java.io.IOException;
 import java.io.File;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 
 
 /**
@@ -106,7 +105,7 @@ public class Initializer {
     public Initializer() throws IOException {
         final String file = System.getProperty("java.util.logging.config.file");
         if (file != null) {
-            final Path path = Paths.get(file).normalize();
+            final Path path = Path.of(file).normalize();
             final StringBuilder buffer = new StringBuilder(600);
             for (String line : Files.readAllLines(path)) {
                 if (!(line = line.trim()).isEmpty() && line.charAt(0) != '#') {
diff --git a/core/sis-utility/src/test/java/org/apache/sis/internal/converter/StringConverterTest.java b/core/sis-utility/src/test/java/org/apache/sis/internal/converter/StringConverterTest.java
index b99fdd118e..f11046b35f 100644
--- a/core/sis-utility/src/test/java/org/apache/sis/internal/converter/StringConverterTest.java
+++ b/core/sis-utility/src/test/java/org/apache/sis/internal/converter/StringConverterTest.java
@@ -25,7 +25,6 @@ import java.net.URL;
 import java.net.URISyntaxException;
 import java.net.MalformedURLException;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.lang.annotation.ElementType;
@@ -264,7 +263,7 @@ public final class StringConverterTest extends TestCase {
     public void testPath() {
         final ObjectConverter<String,Path> c = new StringConverter.Path();
         final String path = "home/user/index.txt".replace('/', File.separatorChar);
-        runInvertibleConversion(c, path, Paths.get(path));
+        runInvertibleConversion(c, path, Path.of(path));
         assertSerializedEquals(c);
     }
 
diff --git a/core/sis-utility/src/test/java/org/apache/sis/test/ProjectDirectories.java b/core/sis-utility/src/test/java/org/apache/sis/test/ProjectDirectories.java
index ca39173cfc..7a6fac4409 100644
--- a/core/sis-utility/src/test/java/org/apache/sis/test/ProjectDirectories.java
+++ b/core/sis-utility/src/test/java/org/apache/sis/test/ProjectDirectories.java
@@ -21,7 +21,6 @@ import java.net.URL;
 import java.net.URISyntaxException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 
 import static org.junit.Assert.*;
 
@@ -69,7 +68,7 @@ public final class ProjectDirectories {
         assertNotNull("Class not found.", resource);
         Path dir;
         try {
-            dir = Paths.get(resource.toURI()).getParent();
+            dir = Path.of(resource.toURI()).getParent();
         } catch (URISyntaxException e) {
             throw new AssertionError(e);
         }
diff --git a/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/landsat/Band.java b/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/landsat/Band.java
index 098523a3d4..e2a9436afc 100644
--- a/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/landsat/Band.java
+++ b/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/landsat/Band.java
@@ -17,7 +17,6 @@
 package org.apache.sis.storage.landsat;
 
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.Optional;
 import org.opengis.util.LocalName;
 import org.opengis.util.GenericName;
@@ -123,7 +122,7 @@ final class Band extends GridResourceWrapper implements SchemaModifier {
         if (parent.directory != null) {
             file = parent.directory.resolve(filename);
         } else {
-            file = Paths.get(filename);
+            file = Path.of(filename);
         }
         final StorageConnector connector = new StorageConnector(file);
         connector.setOption(SchemaModifier.OPTION, this);
diff --git a/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/landsat/LandsatStoreProvider.java b/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/landsat/LandsatStoreProvider.java
index cb16491251..0d847eea11 100644
--- a/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/landsat/LandsatStoreProvider.java
+++ b/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/landsat/LandsatStoreProvider.java
@@ -17,7 +17,6 @@
 package org.apache.sis.storage.landsat;
 
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.Files;
 import java.util.logging.Logger;
 import org.opengis.parameter.ParameterDescriptorGroup;
@@ -193,7 +192,7 @@ public class LandsatStoreProvider extends DataStoreProvider {
      */
     static Path getMetadataFile(final Path directory) {
         if (directory != null) {
-            final Path file = directory.resolve(Paths.get(directory.getFileName().toString().concat("_MTL.txt")));
+            final Path file = directory.resolve(Path.of(directory.getFileName().toString().concat("_MTL.txt")));
             if (Files.isRegularFile(file)) {
                 return file;
             }
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 d62487edde..768372c3af 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
@@ -22,7 +22,6 @@ import java.io.OutputStream;
 import java.io.File;
 import java.net.URI;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
 import java.nio.file.FileSystemNotFoundException;
 import java.nio.charset.Charset;
@@ -162,7 +161,7 @@ public abstract class URIDataStore extends DataStore implements StoreResource, R
             if (location == null) {
                 return new Path[0];
             } else try {
-                path = Paths.get(location);
+                path = Path.of(location);
             } catch (IllegalArgumentException | FileSystemNotFoundException e) {
                 throw new DataStoreException(e);
             }
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 cbba0f4efc..0da1f94cab 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
@@ -33,7 +33,6 @@ import java.net.URI;
 import java.net.URL;
 import java.net.MalformedURLException;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.Files;
 import java.nio.file.InvalidPathException;
 import java.nio.file.FileSystemNotFoundException;
@@ -234,7 +233,7 @@ public abstract class ChannelFactory {
                     }
                 };
             } else try {
-                storage = Paths.get(uri);
+                storage = Path.of(uri);
             } catch (IllegalArgumentException | FileSystemNotFoundException e) {
                 try {
                     storage = uri.toURL();
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java
index e11700a9bf..7ea1c4ac31 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java
@@ -33,7 +33,6 @@ import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.WritableByteChannel;
 import java.nio.channels.SeekableByteChannel;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.OpenOption;
 import java.nio.file.StandardOpenOption;
 import java.nio.file.FileSystemNotFoundException;
@@ -407,7 +406,7 @@ public final class IOUtilities extends Static {
 
     /**
      * Converts a {@link URL} to a {@link Path}. This is equivalent to a call to the standard
-     * {@link URL#toURI()} method followed by a call to the {@link Paths#get(URI)} static method,
+     * {@link URL#toURI()} method followed by a call to the {@link Path#of(URI)} static method,
      * except for the following functionalities:
      *
      * <ul>
@@ -422,7 +421,7 @@ public final class IOUtilities extends Static {
      * @return the path for the given URL, or {@code null} if the given URL was null.
      * @throws IOException if the URL cannot be converted to a path.
      *
-     * @see Paths#get(URI)
+     * @see Path#of(URI)
      */
     public static Path toPath(final URL url, final String encoding) throws IOException {
         if (url == null) {
@@ -430,7 +429,7 @@ public final class IOUtilities extends Static {
         }
         final URI uri = toURI(url, encoding);
         try {
-            return Paths.get(uri);
+            return Path.of(uri);
         } catch (IllegalArgumentException | FileSystemNotFoundException cause) {
             final String message = Exceptions.formatChainedMessages(null,
                     Errors.format(Errors.Keys.IllegalArgumentValue_2, "URL", url), cause);
@@ -516,9 +515,9 @@ public final class IOUtilities extends Static {
         } else if (path instanceof File) {
             return ((File) path).toPath();
         } else if (path instanceof URI) {
-            return Paths.get((URI) path);
+            return Path.of((URI) path);
         } else if (path instanceof CharSequence) {
-            return Paths.get(path.toString());
+            return Path.of(path.toString());
         } else {
             return null;
         }
diff --git a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/folder/StoreTest.java b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/folder/StoreTest.java
index a7b5e1320e..c3f72edac5 100644
--- a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/folder/StoreTest.java
+++ b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/folder/StoreTest.java
@@ -20,7 +20,6 @@ import java.io.IOException;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -56,7 +55,7 @@ public final class StoreTest extends TestCase {
         final URL sample = StoreTest.class.getResource("test-data/README.txt");
         assertNotNull("Test data not found", sample);
         assumeTrue(sample.getProtocol().equals("file"));
-        return Paths.get(sample.toURI()).getParent();
+        return Path.of(sample.toURI()).getParent();
     }
 
     /**


[sis] 03/03: When the `InputStream` to wrap in a `ChannelDataInput` is backed by an array, wrap the underlying array (in read-only mode) instead of copying it.

Posted by de...@apache.org.
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 f96f7ad0f81b69506c16b18c44730fb238fd57a8
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Thu Feb 9 14:55:16 2023 +0100

    When the `InputStream` to wrap in a `ChannelDataInput` is backed by an array,
    wrap the underlying array (in read-only mode) instead of copying it.
---
 .../sis/internal/sql/postgis/RasterReader.java     |  14 ++-
 .../sis/internal/storage/io/ChannelDataInput.java  |  27 +++--
 .../storage/io/InputStreamArrayGetter.java         | 135 +++++++++++++++++++++
 .../storage/io/InputStreamArrayGetterTest.java     |  62 ++++++++++
 .../apache/sis/test/suite/StorageTestSuite.java    |   1 +
 5 files changed, 221 insertions(+), 18 deletions(-)

diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/postgis/RasterReader.java b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/postgis/RasterReader.java
index 8b056cbc5a..70c5633727 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/postgis/RasterReader.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/postgis/RasterReader.java
@@ -37,7 +37,6 @@ import java.awt.image.DataBufferDouble;
 import java.awt.image.WritableRaster;
 import java.awt.image.BufferedImage;
 import java.awt.image.RasterFormatException;
-import java.nio.channels.Channels;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.coverage.SampleDimension;
 import org.apache.sis.coverage.grid.GridCoverage;
@@ -46,6 +45,7 @@ import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.internal.coverage.j2d.ColorModelFactory;
 import org.apache.sis.internal.referencing.j2d.AffineTransform2D;
+import org.apache.sis.internal.storage.io.InputStreamArrayGetter;
 import org.apache.sis.internal.storage.io.ChannelDataInput;
 import org.apache.sis.internal.sql.feature.InfoStatements;
 import org.apache.sis.internal.util.Constants;
@@ -70,7 +70,7 @@ import static org.apache.sis.internal.sql.postgis.Band.OPPOSITE_SIGN;
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.4
  * @since   1.2
  */
 public final class RasterReader extends RasterFormat {
@@ -398,9 +398,11 @@ public final class RasterReader extends RasterFormat {
      * @throws IOException if an error occurred while reading data from the input stream.
      */
     public ChannelDataInput channel(final InputStream input) throws IOException {
-        if (buffer == null) {
-            buffer = ByteBuffer.allocate(8192);
-        }
-        return new ChannelDataInput("raster", Channels.newChannel(input), buffer, false);
+        return InputStreamArrayGetter.channel("raster", input, () -> {
+            if (buffer == null) {
+                buffer = ByteBuffer.allocate(8192);
+            }
+            return buffer;
+        });
     }
 }
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java
index 40eb30dbe9..ec18853ec8 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java
@@ -86,6 +86,9 @@ public class ChannelDataInput extends ChannelData {
      * If the buffer already contains some data, then the {@code filled} argument shall be {@code true}.
      * Otherwise (e.g. if it is a newly created buffer), then {@code filled} shall be {@code false}.
      *
+     * <p><b>Tip:</b>
+     * for building a data input from an input stream, see {@link InputStreamArrayGetter}.</p>
+     *
      * @param  filename  a short identifier (typically a filename without path) used for formatting error message.
      * @param  channel   the channel from where data are read.
      * @param  buffer    the buffer where to copy the data.
@@ -105,18 +108,6 @@ public class ChannelDataInput extends ChannelData {
         }
     }
 
-    /**
-     * Creates a new input stream from the given {@code ChannelDataInput}.
-     * This constructor is invoked when we need to change the implementation class.
-     * The old input should not be used anymore after this constructor has been invoked.
-     *
-     * @param  input  the existing instance from which to takes the channel and buffer.
-     */
-    ChannelDataInput(final ChannelDataInput input) {
-        super(input);
-        channel = input.channel;
-    }
-
     /**
      * Creates a new instance for a buffer filled with the bytes to use.
      * This constructor uses an independent, read-only view of the given buffer.
@@ -130,6 +121,18 @@ public class ChannelDataInput extends ChannelData {
         channel = new NullChannel();
     }
 
+    /**
+     * Creates a new input stream from the given {@code ChannelDataInput}.
+     * This constructor is invoked when we need to change the implementation class.
+     * The old input should not be used anymore after this constructor has been invoked.
+     *
+     * @param  input  the existing instance from which to takes the channel and buffer.
+     */
+    ChannelDataInput(final ChannelDataInput input) {
+        super(input);
+        channel = input.channel;
+    }
+
     /**
      * Returns the length of the stream (in bytes), or -1 if unknown.
      * The length is relative to the channel position at {@linkplain #ChannelDataInput construction time}.
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/InputStreamArrayGetter.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/InputStreamArrayGetter.java
new file mode 100644
index 0000000000..7432a391a7
--- /dev/null
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/InputStreamArrayGetter.java
@@ -0,0 +1,135 @@
+/*
+ * 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.sis.internal.storage.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.ByteArrayInputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.function.Supplier;
+import org.apache.sis.util.logging.Logging;
+import org.apache.sis.internal.storage.StoreUtilities;
+
+
+/**
+ * A hack for getting the backing array of an input stream if that array exists.
+ * This class searches the array in the following locations:
+ *
+ * <ul>
+ *   <li>{@link ByteArrayInputStream#buf} together with offset and length.
+ *       Those fields have {@code protected} access, so they are committed Java API.
+ *       However as of Java 19, there is no public accessor for them.</li>
+ * </ul>
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.4
+ * @since   1.4
+ */
+public final class InputStreamArrayGetter extends OutputStream {
+    /**
+     * The buffer wrapping the array, or {@code null} if unknown.
+     * This buffer is not read-only, but nevertheless should not be modified.
+     */
+    private ByteBuffer buffer;
+
+    /**
+     * Creates a pseudo output stream to use as a trick for getting the backing array.
+     */
+    private InputStreamArrayGetter() {
+    }
+
+    /**
+     * Whether it is hopefully safe to apply the trick used by this class for getting the backing array.
+     * The trick is that the {@link ByteArrayInputStream#transferTo(OutputStream)} implementation gives
+     * the backing array in argument in a call to {@link InputStream#write(byte[], int, int)} method.
+     * This is verified by looking at the OpenJDK source code, and presumed relatively stable because
+     * the code uses only protected fields and public methods, which are committed API.
+     * But because users could override the {@code transferTo(…)} method in a subclass,
+     * we rely on this strick only if the method implementation is the one provided by
+     * the standard {@link ByteArrayInputStream} class.
+     *
+     * @param  input  the input stream for which to verify the implementation class.
+     * @return whether the implementation is the OpenJDK one.
+     */
+    private static boolean isKnownImplementation(final InputStream input) {
+        try {
+            return input.getClass().getMethod("transferTo", OutputStream.class).getDeclaringClass() == ByteArrayInputStream.class;
+        } catch (NoSuchMethodException e) {
+            // Should not happen because we requested a method which should exist.
+            Logging.unexpectedException(StoreUtilities.LOGGER, InputStreamArrayGetter.class, "isKnownImplementation", e);
+            return false;
+        }
+    }
+
+    /**
+     * Creates a new data input for the given input stream.
+     * If the input stream is backed by an array, the array will be wrapped in a read-only mode.
+     *
+     * @param  filename  a short identifier (typically a filename without path) used for formatting error message.
+     * @param  input     the input stream from where data are read.
+     * @param  bs        supplier of the buffer where to copy the data.
+     * @return the data input using a readable channel.
+     * @throws IOException if an error occurred while reading the input stream.
+     */
+    public static ChannelDataInput channel(final String filename, final InputStream input, final Supplier<ByteBuffer> bs)
+            throws IOException
+    {
+        if (isKnownImplementation(input)) {
+            final InputStreamArrayGetter getter = new InputStreamArrayGetter();
+            input.transferTo(getter);
+            if (getter.buffer != null) {
+                return new ChannelDataInput(filename, getter.buffer);
+            }
+        }
+        final ReadableByteChannel channel = Channels.newChannel(input);
+        return new ChannelDataInput(filename, channel, bs.get(), false);
+    }
+
+    /**
+     * Invoked by {@link ByteArrayInputStream#transferTo(OutputStream)}.
+     * We use this method as a callback for getting the underlying array.
+     *
+     * @param  array   the data.
+     * @param  offset  the start offset in the array.
+     * @param  length  the number of valid bytes in the array.
+     * @throws IOException if this method is invoked more than once.
+     */
+    @Override
+    public void write(final byte[] array, final int offset, final int length) throws IOException {
+        if (buffer == null) {
+            buffer = ByteBuffer.wrap(array, offset, length);
+        } else {
+            super.write(array, offset, length);
+        }
+    }
+
+    /**
+     * Should never be invoked. If this method is nevertheless invoked,
+     * then the {@link ByteArrayInputStream#transferTo(OutputStream)}
+     * implementation is not what we expected.
+     *
+     * @param  b  ignored.
+     * @throws IOException always thrown.
+     */
+    @Override
+    public void write(int b) throws IOException {
+        throw new IOException("Unexpected implementation.");
+    }
+}
diff --git a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/InputStreamArrayGetterTest.java b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/InputStreamArrayGetterTest.java
new file mode 100644
index 0000000000..ae4ea03579
--- /dev/null
+++ b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/InputStreamArrayGetterTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.sis.internal.storage.io;
+
+import java.io.IOException;
+import java.io.ByteArrayInputStream;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests the {@link InputStreamArrayGetter} class.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.4
+ * @since   1.4
+ */
+public final class InputStreamArrayGetterTest extends TestCase {
+    /**
+     * Tests the creation of a channel data input which uses directly the array.
+     *
+     * @throws IOException if an error occurred while creating the channel data input.
+     */
+    @Test
+    public void testDirectChannel() throws IOException {
+        final var array = new byte[20];
+        for (int i=0; i<array.length; i++) {
+            array[i] = (byte) ((i ^ 5772) * 37);
+        }
+        final int offset = 7;
+        final var input  = new ByteArrayInputStream(array, offset, 9);
+        final ChannelDataInput data = InputStreamArrayGetter.channel("Test", input, () -> {
+            throw new AssertionError("Should not create new buffer.");
+        });
+        /*
+         * Replace a few values in the backing array AFTER the `ChannelDataInput` creation.
+         * If the data input does not wrap the array, the changes below would be unnoticed.
+         */
+        array[offset + 1] = 99;     // Replace   20.
+        array[offset + 4] = 100;    // Replace -125.
+        final byte[] expected = {23, 99, 57, 94, 100, -128};
+        for (int i=0; i<expected.length; i++) {
+            assertEquals(expected[i], data.readByte());
+        }
+    }
+}
diff --git a/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java b/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
index 8a8556ede6..e84a691f07 100644
--- a/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
+++ b/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
@@ -40,6 +40,7 @@ import org.junit.BeforeClass;
     org.apache.sis.internal.storage.io.HyperRectangleReaderTest.class,
     org.apache.sis.internal.storage.io.RewindableLineReaderTest.class,
     org.apache.sis.internal.storage.io.FileCacheByteChannelTest.class,
+    org.apache.sis.internal.storage.io.InputStreamArrayGetterTest.class,
     org.apache.sis.internal.storage.MetadataBuilderTest.class,
     org.apache.sis.internal.storage.RangeArgumentTest.class,
     org.apache.sis.internal.storage.MemoryGridResourceTest.class,