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 2026/04/15 11:27:04 UTC

(sis) 01/02: Edit documentation, add `@see` tags, avoid forcing conversion to URI.

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 f1883b4207ba9056f482ad42381a8fca0d747d8a
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Wed Apr 15 13:25:49 2026 +0200

    Edit documentation, add `@see` tags, avoid forcing conversion to URI.
---
 .../org/apache/sis/storage/StorageConnector.java   | 83 ++++++++++++----------
 1 file changed, 46 insertions(+), 37 deletions(-)

diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/StorageConnector.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/StorageConnector.java
index 830fa4d50d..5237e8e985 100644
--- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/StorageConnector.java
+++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/StorageConnector.java
@@ -52,6 +52,7 @@ import javax.sql.DataSource;
 import org.apache.sis.util.Debug;
 import org.apache.sis.util.Classes;
 import org.apache.sis.util.Workaround;
+import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ObjectConverters;
 import org.apache.sis.util.UnconvertibleObjectException;
 import org.apache.sis.util.resources.Errors;
@@ -77,7 +78,6 @@ import org.apache.sis.io.stream.ChannelImageOutputStream;
 import org.apache.sis.io.stream.InternalOptionKey;
 import org.apache.sis.system.Configuration;
 import org.apache.sis.setup.OptionKey;
-import org.apache.sis.util.ArgumentChecks;
 
 
 /**
@@ -631,7 +631,7 @@ public class StorageConnector implements Serializable {
      * Creates a new data store connection wrapping the given input/output object.
      * The object can be of any type, but the class javadoc lists the most typical ones.
      *
-     * @param storage  the input/output object as a URL, file, image input stream, <i>etc.</i>.
+     * @param storage  the input/output object as a <abbr>URL</abbr>, file, image input stream, <i>etc.</i>.
      */
     public StorageConnector(final Object storage) {
         this.storage = Objects.requireNonNull(storage);
@@ -642,7 +642,7 @@ public class StorageConnector implements Serializable {
      * The new storage connector inherits all options that were specified in the parent connector.
      *
      * @param  parent  the storage connector from which to inherit options.
-     * @param storage  the input/output object as a URL, file, image input stream, <i>etc.</i>.
+     * @param storage  the input/output object as a <abbr>URL</abbr>, file, image input stream, <i>etc.</i>.
      *
      * @since 1.5
      */
@@ -659,7 +659,7 @@ public class StorageConnector implements Serializable {
      *
      * <ul>
      *   <li>{@link OptionKey#ENCODING}     for decoding characters in an input stream, if needed.</li>
-     *   <li>{@link OptionKey#URL_ENCODING} for converting URL to URI or filename, if needed.</li>
+     *   <li>{@link OptionKey#URL_ENCODING} for converting <abbr>URL</abbr> to <abbr>URI</abbr> or filename, if needed.</li>
      *   <li>{@link OptionKey#OPEN_OPTIONS} for specifying whether the data store shall be read only or read/write.</li>
      *   <li>{@link OptionKey#BYTE_BUFFER}  for allowing users to control the byte buffer to be created.</li>
      * </ul>
@@ -708,7 +708,7 @@ public class StorageConnector implements Serializable {
      *
      * <ul>
      *   <li>For {@link Path}, {@link File}, {@link URI} or {@link URL}
-     *       instances, this method uses dedicated API like {@link Path#getFileName()}.</li>
+     *       instances, this method uses dedicated <abbr>API</abbr> like {@link Path#getFileName()}.</li>
      *   <li>For {@link CharSequence} instances, this method gets a string representation of the storage object
      *       and returns the part after the last {@code '/'} character or platform-dependent name separator.</li>
      *   <li>For instances of unknown type, this method builds a string representation using the class name.
@@ -749,15 +749,17 @@ public class StorageConnector implements Serializable {
      * the following choices based on the type of the {@linkplain #getStorage() storage} object:
      *
      * <ul>
-     *   <li>For {@link Path}, {@link File}, {@link URI}, {@link URL} or
-     *       {@link CharSequence} instances, this method returns the string after the last {@code '.'} character
-     *       in the filename, provided that the {@code '.'} is not the first filename character. This may be an
-     *       empty string if the filename has no extension, but never {@code null}.</li>
-     *   <li>For instances of unknown type, this method returns {@code null}.</li>
+     *   <li>For {@link Path}, {@link File}, {@link URI}, {@link URL} or {@link CharSequence} instances,
+     *       returns the sub-string after the last {@code '.'} character in the filename,
+     *       provided that the {@code '.'} is not the first filename character.
+     *       If the filename has no extension, returns an empty string (not {@code null}).</li>
+     *   <li>For instances of unknown type, returns {@code null}.</li>
      * </ul>
      *
      * @return the filename extension, or an empty string if none,
      *         or {@code null} if the storage is an object of unknown type.
+     *
+     * @see #pathEndsWith(String, boolean)
      */
     public String getFileExtension() {
         if (extension == null) {
@@ -1101,28 +1103,29 @@ public class StorageConnector implements Serializable {
     }
 
     /**
-     * Tests if the content of the storage from this connector starts with the given signature.
-     * <p>
+     * Tests if the content of the storage specified by this connector starts with the given signature.
      * If the storage cannot be read as a sequence of bytes, for example if the storage is a connection to a database,
      * then this method returns {@code UNSUPPORTED_STORAGE}.
      *
-     * @param signature to test, not null
-     * @return {@code SUPPORTED} if content matches,
+     * @param  signature  sequence of bytes to test as a signature.
+     * @return {@code SUPPORTED} if content matches the given signature,
      *         {@code INSUFFICIENT_BYTES} if the buffer is too small,
      *         {@code UNSUPPORTED_STORAGE} otherwise.
+     * @throws NullPointerException if {@code signature} is null.
      * @throws DataStoreException if an error occurred while opening or reading.
+     *
+     * @see DataStoreProvider#probeContent(StorageConnector)
+     *
      * @since 1.7
      */
-    public ProbeResult contentStartsWith(byte[] signature) throws DataStoreException {
+    public ProbeResult contentStartsWith(final byte[] signature) throws DataStoreException {
         ArgumentChecks.ensureNonNull("signature", signature);
-
         final ByteBuffer buffer = getStorageAs(ByteBuffer.class);
         if (buffer == null) return ProbeResult.UNSUPPORTED_STORAGE;
+        buffer.mark();
         try {
-            buffer.mark();
+            // Compare signatures.
             final int remaining = buffer.remaining();
-
-            // compare signatures
             for (int i = 0; i < signature.length; i++) {
                 if (i >= remaining) {
                     return ProbeResult.INSUFFICIENT_BYTES;
@@ -1138,30 +1141,36 @@ public class StorageConnector implements Serializable {
     }
 
     /**
-     * Tests if the data path from this connector ends with the given suffix.
-     * We test the suffix here and not the extension because several formats
-     * used combined extensions, like .meta.xml or .bin.gz.
-     * Restricting ourselves to file extension is ambigious in such cases, this is why suffix is used instead.
-     * <p>
-     * This method fallback on {@linkplain  String#regionMatches(boolean, int, java.lang.String, int, int) }
-     * for the suffix test.
-     *
-     * @param suffix to test, not null
-     * @param ignoreCase  if true, ignore case when comparing characters.
+     * Tests if the path or <abbr>URI</abbr> of the input/output object ends with the given suffix.
+     * The suffix is compared with no special treatment for the {@code '.'} character.
+     * Therefore, this method is better suited than {@link #getFileExtension()}
+     * for combined extensions such as {@code ".meta.xml"} or {@code ".bin.gz"}.
+     *
+     * <p>The default implementation compare the suffix using
+     * {@linkplain String#regionMatches(boolean, int, java.lang.String, int, int) String.regionMatches(…)}.
+     * See that method for details about how cases are ignored if {@code ignoreCase} is true.</p>
+     *
+     * @param  suffix      the suffix to test. Shall not be empty.
+     * @param  ignoreCase  if true, ignore case when comparing characters.
      * @return {@code SUPPORTED} if suffix matches,
      *         {@code UNSUPPORTED_STORAGE} otherwise.
      * @throws DataStoreException if an error occurred while opening or reading.
+     *
+     * @see #getFileExtension()
+     * @see DataStoreProvider#probeContent(StorageConnector)
+     *
      * @since 1.7
      */
-    public ProbeResult pathEndsWith(String suffix, boolean ignoreCase) throws DataStoreException {
+    public ProbeResult pathEndsWith(final String suffix, final boolean ignoreCase) throws DataStoreException {
         ArgumentChecks.ensureNonEmpty("suffix", suffix);
-        final URI uri = getStorageAs(URI.class);
-        if (uri == null) return ProbeResult.UNSUPPORTED_STORAGE;
-
-        name = uri.isOpaque() ? uri.getSchemeSpecificPart() : uri.getPath();
-        final int suffixLength = suffix.length();
-        return name.regionMatches(ignoreCase, name.length()-suffixLength, suffix, 0, suffixLength) ?
-               ProbeResult.SUPPORTED : ProbeResult.UNSUPPORTED_STORAGE;
+        final String filename = IOUtilities.filename(storage);
+        if (filename != null) {
+            final int suffixLength = suffix.length();
+            if (filename.regionMatches(ignoreCase, filename.length() - suffixLength, suffix, 0, suffixLength)) {
+                return ProbeResult.SUPPORTED;
+            }
+        }
+        return ProbeResult.UNSUPPORTED_STORAGE;
     }
 
     /**