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 2022/12/14 19:22:42 UTC

[sis] 03/03: Improve the error message when failing to open a connection on an AWS S3 bucket.

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 fae2e065467f5a89fccc9dd4c22065f6a79c29f3
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Wed Dec 14 20:21:44 2022 +0100

    Improve the error message when failing to open a connection on an AWS S3 bucket.
---
 .../org/apache/sis/internal/gui/DataStoreOpener.java   |  7 +++++--
 .../org/apache/sis/internal/gui/ExceptionReporter.java |  6 +++++-
 .../org/apache/sis/cloud/aws/internal/Resources.java   |  5 +++++
 .../apache/sis/cloud/aws/internal/Resources.properties |  1 +
 .../sis/cloud/aws/internal/Resources_fr.properties     |  1 +
 .../java/org/apache/sis/cloud/aws/s3/FileService.java  | 18 ++++++++++++++++--
 .../main/java/org/apache/sis/cloud/aws/s3/KeyPath.java |  6 +++---
 .../java/org/apache/sis/cloud/aws/s3/package-info.java |  2 +-
 .../apache/sis/internal/storage/io/ChannelFactory.java |  4 ++--
 .../apache/sis/internal/storage/io/IOUtilities.java    |  6 ++++++
 .../java/org/apache/sis/storage/StorageConnector.java  | 11 ++++++++---
 .../main/java/org/apache/sis/storage/package-info.java |  2 +-
 12 files changed, 54 insertions(+), 15 deletions(-)

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 5eee24824c..ee57ad6dc2 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
@@ -204,9 +204,12 @@ public final class DataStoreOpener extends Task<DataStore> {
         if (source instanceof StorageConnector) {
             return ((StorageConnector) source).getStorageName();
         }
-        String name = IOUtilities.filename(source);
+        String name = Strings.trimOrNull(IOUtilities.filename(source));
         if (name == null) {
-            name = Vocabulary.format(Vocabulary.Keys.Unknown);
+            name = Strings.trimOrNull(IOUtilities.toString(source));
+            if (name == null) {
+                name = Vocabulary.format(Vocabulary.Keys.Unknown);
+            }
         }
         return name;
     }
diff --git a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ExceptionReporter.java b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ExceptionReporter.java
index 42af7b15bf..b64d7b8f37 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ExceptionReporter.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ExceptionReporter.java
@@ -293,7 +293,11 @@ public final class ExceptionReporter extends Widget {
             Platform.runLater(() -> show(owner, title, text, exception));
             return;
         }
-        String message = exception.getLocalizedMessage();
+        String message = null;
+        for (Throwable e = exception; e != null; e = e.getCause()) {
+            message = e.getLocalizedMessage();
+            if (message != null && !message.equalsIgnoreCase(text)) break;
+        }
         if (message == null) {
             message = Classes.getShortClassName(exception);
         }
diff --git a/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/internal/Resources.java b/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/internal/Resources.java
index a422154e41..f567e52c63 100644
--- a/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/internal/Resources.java
+++ b/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/internal/Resources.java
@@ -71,6 +71,11 @@ public final class Resources extends IndexedResourceBundle {
          */
         public static final short FileSystemInitialized_2 = 4;
 
+        /**
+         * Invalid bucket name in “{0}”.
+         */
+        public static final short InvalidBucketName_1 = 8;
+
         /**
          * Missing {0,choice,0#public|1#secret} access key in “{1}” URI.
          */
diff --git a/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/internal/Resources.properties b/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/internal/Resources.properties
index 5e0486617a..4fd28f876c 100644
--- a/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/internal/Resources.properties
+++ b/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/internal/Resources.properties
@@ -22,6 +22,7 @@
 CanNotChangeToAbsolutePath        = Cannot change a relative path to an absolute path.
 EmptyPath                         = Empty path.
 FileSystemInitialized_2           = File system {0,choice,0#not|1#already} initialized for the \u201c{1}\u201d access key.
+InvalidBucketName_1               = Invalid bucket name in \u201c{0}\u201d.
 MissingAccessKey_2                = Missing {0,choice,0#public|1#secret} access key in \u201c{1}\u201d URI.
 MustBeAbsolutePath                = Specified path must be an absolute S3 path.
 MustHaveKeyComponent              = Specified path cannot be the root.
diff --git a/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/internal/Resources_fr.properties b/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/internal/Resources_fr.properties
index 9086b8e853..110a56ad77 100644
--- a/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/internal/Resources_fr.properties
+++ b/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/internal/Resources_fr.properties
@@ -27,6 +27,7 @@
 CanNotChangeToAbsolutePath        = Ne peut pas changer un chemin relatif en chemin absolu.
 EmptyPath                         = Le chemin est vide.
 FileSystemInitialized_2           = Le syst\u00e8me de fichier {0,choice,0#n\u2019a pas \u00e9t\u00e9|1#est d\u00e9j\u00e0} initialis\u00e9 pour la cl\u00e9 d\u2019acc\u00e8s \u00ab\u202f{1}\u202f\u00bb.
+InvalidBucketName_1               = Le nom du compartiment dans \u00ab\u202f{0}\u202f\u00bb est invalide.
 MissingAccessKey_2                = Il manque la cl\u00e9 d'acc\u00e8s {0,choice,0#publique|1#secr\u00e8te} dans l'URI \u00ab\u202f{1}\u202f\u00bb.
 MustBeAbsolutePath                = Le chemin sp\u00e9cifi\u00e9 doit \u00eatre un chemin S3 absolu.
 MustHaveKeyComponent              = Le chemin sp\u00e9cifi\u00e9 ne peut pas \u00eatre la racine.
diff --git a/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/s3/FileService.java b/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/s3/FileService.java
index d1f7b63803..9b44d65de7 100644
--- a/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/s3/FileService.java
+++ b/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/s3/FileService.java
@@ -43,6 +43,7 @@ import java.nio.file.NotDirectoryException;
 import java.nio.file.AccessDeniedException;
 import java.nio.file.StandardOpenOption;
 import java.nio.file.attribute.BasicFileAttributeView;
+import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.collection.Containers;
@@ -74,7 +75,7 @@ import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
  * instead of the data to access, and can be a global configuration for the server.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.4
  * @since   1.2
  * @module
  */
@@ -290,7 +291,20 @@ public class FileService extends FileSystemProvider {
             // TODO: we may need a way to get password here.
             fs = fileSystems.computeIfAbsent(accessKey, (key) -> new ClientFileSystem(FileService.this, null, key, null, null));
         }
-        return new KeyPath(fs, uri.getHost(), new String[] {uri.getPath()}, true);
+        String host = uri.getHost();
+        if (host == null) {
+            /*
+             * The host is null if the authority contains characters that are invalid for a host name.
+             * For example if the host contains underscore character ('_'), then it is considered invalid.
+             * We could use the authority instead, but that authority may contain a user name, port number, etc.
+             * Current version do not try to parse that string.
+             */
+            host = uri.getAuthority();
+            if (host == null) host = uri.toString();
+            throw new IllegalArgumentException(Resources.format(Resources.Keys.InvalidBucketName_1, host));
+        }
+        final String path = uri.getPath();
+        return new KeyPath(fs, host, (path != null) ? new String[] {path} : CharSequences.EMPTY_ARRAY, true);
     }
 
     /**
diff --git a/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/s3/KeyPath.java b/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/s3/KeyPath.java
index 87e10e774e..117c33a966 100644
--- a/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/s3/KeyPath.java
+++ b/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/s3/KeyPath.java
@@ -48,7 +48,7 @@ import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
  * The interpretation of {@link ClientFileSystem#separator} as a path separator is done by this class.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.4
  * @since   1.2
  * @module
  */
@@ -338,8 +338,8 @@ final class KeyPath implements Path {
     /**
      * Returns a new path with the same file system than this path.
      */
-    private KeyPath newPath(final String path) {
-        return new KeyPath(fs, path, CharSequences.EMPTY_ARRAY, false);
+    private KeyPath newPath(final String other) {
+        return new KeyPath(fs, Objects.requireNonNull(other, "other"), CharSequences.EMPTY_ARRAY, false);
     }
 
     /**
diff --git a/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/s3/package-info.java b/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/s3/package-info.java
index ba209f9fcb..92e86f5e6f 100644
--- a/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/s3/package-info.java
+++ b/cloud/sis-cloud-aws/src/main/java/org/apache/sis/cloud/aws/s3/package-info.java
@@ -49,7 +49,7 @@
  * All classes provided by this package are safe of usage in multi-threading environment.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.4
  *
  * @see <a href="https://sdk.amazonaws.com/java/api/latest/index.html">AWS SDK for Java</a>
  *
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 117f4035a4..943a8fe371 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
@@ -230,8 +230,8 @@ public abstract class ChannelFactory {
                 try {
                     storage = uri.toURL();
                 } catch (MalformedURLException ioe) {
-                    ioe.addSuppressed(e);
-                    throw ioe;
+                    e.addSuppressed(ioe);
+                    throw e;
                 }
                 /*
                  * We have been able to convert to URL, but the given OpenOptions may not be used.
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 fba5a3cd8d..60616119ad 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
@@ -99,6 +99,9 @@ public final class IOUtilities extends Static {
      *
      * @param  path  the path as an instance of one of the above-cited types, or {@code null}.
      * @return the filename in the given path, or {@code null} if the given object is null or of unknown type.
+     *
+     * @see #extension(Object)
+     * @see #toString(Object)
      */
     public static String filename(final Object path) {
         return part(path, false);
@@ -176,6 +179,9 @@ public final class IOUtilities extends Static {
      *
      * @param  path  the path for which to return a string representation.
      * @return the string representation, or {@code null} if none.
+     *
+     * @see #filename(Object)
+     * @see #extension(Object)
      */
     public static String toString(final Object path) {
         /*
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 b5c6ea837d..0765ebb80e 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
@@ -100,7 +100,7 @@ import org.apache.sis.setup.OptionKey;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Alexis Manin (Geomatys)
- * @version 1.3
+ * @version 1.4
  * @since   0.3
  * @module
  */
@@ -227,6 +227,8 @@ public class StorageConnector implements Serializable {
     /**
      * A name for the input/output object, or {@code null} if none.
      * This field is initialized only when first needed.
+     *
+     * @see #getStorageName()
      */
     private transient String name;
 
@@ -639,9 +641,12 @@ public class StorageConnector implements Serializable {
      */
     public String getStorageName() {
         if (name == null) {
-            name = IOUtilities.filename(storage);
+            name = Strings.trimOrNull(IOUtilities.filename(storage));
             if (name == null) {
-                name = Classes.getShortClassName(storage);
+                name = Strings.trimOrNull(IOUtilities.toString(storage));
+                if (name == null) {
+                    name = Classes.getShortClassName(storage);
+                }
             }
         }
         return name;
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/package-info.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/package-info.java
index e70c106729..b2be40c355 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/storage/package-info.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/package-info.java
@@ -26,7 +26,7 @@
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.3
+ * @version 1.4
  * @since   0.3
  * @module
  */