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 2d3c96abbc0e0b4d8c0ee0a58229896388d44979
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Oct 2 16:47:47 2024 +0200

    Better check of whether a terminal is available before to propose to 
download EPSG data.
    This is needed for avoiding undesired prompts during CI builds.
---
 .../apache/sis/console/ResourcesDownloader.java    |  9 +++++----
 .../factory/ConcurrentAuthorityFactory.java        |  4 ++--
 .../factory/sql/InstallationScriptProvider.java    |  2 +-
 .../main/org/apache/sis/pending/jdk/JDK22.java     |  2 +-
 .../apache/sis/setup/InstallationResources.java    | 22 ++++++++++++++++++----
 .../apache/sis/setup/OptionalInstallations.java    | 10 +++++++++-
 .../gui/internal/io/OptionalDataDownloader.java    | 15 +++++++++++++++
 .../resources/embedded/EmbeddedResourcesTest.java  |  1 -
 8 files changed, 51 insertions(+), 14 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/ResourcesDownloader.java
 
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/ResourcesDownloader.java
index 94e9175e42..fdd143eac1 100644
--- 
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/ResourcesDownloader.java
+++ 
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/ResourcesDownloader.java
@@ -27,6 +27,7 @@ import org.apache.sis.util.privy.X364;
 import org.apache.sis.system.Fallback;
 import org.apache.sis.system.Environment;
 import org.apache.sis.setup.OptionalInstallations;
+import org.apache.sis.pending.jdk.JDK22;
 
 
 /**
@@ -102,14 +103,14 @@ public class ResourcesDownloader extends 
OptionalInstallations {
     /**
      * Returns the name of the authority who provides data under non-Apache 
terms of use.
      * If this {@code ResourcesDownloader} cannot ask user's agreement because 
there is
-     * no {@link Console} attached to the current Java virtual machine, then 
this method
-     * returns an empty set.
+     * no {@link Console} attached to the current Java virtual machine or the 
console is
+     * not {@linkplain Console#isTerminal() a terminal}, then this method 
returns an empty set.
      *
-     * @return {@code "EPSG"} or an empty set.
+     * @return {@code "EPSG"} or an empty set in this class cannot ask user's 
agreement.
      */
     @Override
     public Set<String> getAuthorities() {
-        return (console != null) ? super.getAuthorities() : Set.of();
+        return (console != null && JDK22.isTerminal(console)) ? 
super.getAuthorities() : Set.of();
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
index 354339a2fa..cb507103ed 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
@@ -430,8 +430,8 @@ public abstract class ConcurrentAuthorityFactory<DAO 
extends GeodeticAuthorityFa
                 if (usage == null) {
                     final DAO factory = newDataAccess();
                     if (factory == null) {
-                        UnavailableFactoryException e = new 
UnavailableFactoryException(Errors.format(
-                                Errors.Keys.FactoryNotFound_1, 
GeodeticAuthorityFactory.class));
+                        var e = new UnavailableFactoryException(
+                                Errors.format(Errors.Keys.FactoryNotFound_1, 
GeodeticAuthorityFactory.class));
                         e.setUnavailableFactory(this);
                         throw e;
                     }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java
index 88a2787b61..8f6ea07f73 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java
@@ -345,7 +345,7 @@ public abstract class InstallationScriptProvider extends 
InstallationResources {
          * or {@code "unavailable"} otherwise.
          *
          * @return {@code "EPSG"} if the SQL scripts for installing the EPSG 
dataset are available,
-         *         or {@code "unavailable"} otherwise.
+         *         or an empty set otherwise.
          */
         @Override
         public Set<String> getAuthorities() {
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/jdk/JDK22.java 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/jdk/JDK22.java
index b21b9f84c0..adc7887cf7 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/jdk/JDK22.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/jdk/JDK22.java
@@ -38,7 +38,7 @@ public final class JDK22 {
         try {
             return (Boolean) Console.class.getMethod("isTerminal").invoke(c);
         } catch (ReflectiveOperationException e) {
-            return false;
+            return true;
         }
     }
 }
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/InstallationResources.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/InstallationResources.java
index 10e088cb91..790c6922ac 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/InstallationResources.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/InstallationResources.java
@@ -78,8 +78,11 @@ public abstract class InstallationResources {
     }
 
     /**
-     * {@return installation resources found on the module path}.
+     * Returns all installation resources found on the module path, regardless 
is supported or not.
+     * Callers should filter the services for executing only those where 
{@link #getAuthorities()}
+     * returns a non-empty set.
      *
+     * @return installation resources found on the module path.
      * @since 1.4
      */
     public static ServiceLoader<InstallationResources> load() {
@@ -98,17 +101,28 @@ public abstract class InstallationResources {
      *   <tr><td>{@code "Embedded"}</td> <td>Data source of embedded database 
containing EPSG and other resources.</td></tr>
      * </table>
      *
-     * <div class="note"><b>Note:</b>
+     * <b>Note:</b>
      * {@code "Embedded"} is a pseudo-authority for an embedded database 
containing EPSG and other data.
      * This embedded database is provided by the {@code 
org.apache.sis.referencing.database} module
      * as a convenience for avoiding the need to define a {@code SIS_DATA} 
directory on the local machine.
      * In this particular case, the resource is more for execution than for 
installation.
-     * </div>
      *
+     * <h4>Availability check</h4>
      * This method may return an empty set if this {@code 
InstallationResources} instance did not find the
      * resources (for example because of files not found) or does not have the 
permission to distribute them.
+     * For example, this method should return an empty set in the following 
circumstances:
+     *
+     * <ul>
+     *   <li>The installation requires user's agreement, but this agreement 
cannot be asked because:
+     *     <ul>
+     *       <li>this class is a graphical installer but {@link 
java.awt.GraphicsEnvironment#isHeadless()} returns {@code true}, or</li>
+     *       <li>this class is a command-line installer but {@link 
java.io.Console#isTerminal()} returns {@code false}.</li>
+     *     </ul>
+     *   </li>
+     * </ul>
      *
-     * @return identifiers of resources that this instance can distribute.
+     * @return identifiers of resources that this instance can distribute,
+     *         or an empty set if this {@code InstallationResources} cannot be 
used.
      */
     public abstract Set<String> getAuthorities();
 
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/OptionalInstallations.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/OptionalInstallations.java
index 39eeab8049..4d948cc657 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/OptionalInstallations.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/OptionalInstallations.java
@@ -19,8 +19,11 @@ package org.apache.sis.setup;
 import java.util.Set;
 import java.util.Locale;
 import java.util.ServiceLoader;
+import java.net.URI;
 import java.net.URL;
 import java.net.URLClassLoader;
+import java.net.URISyntaxException;
+import java.net.MalformedURLException;
 import java.io.IOException;
 import java.io.BufferedReader;
 import java.io.FileNotFoundException;
@@ -197,7 +200,12 @@ public abstract class OptionalInstallations extends 
InstallationResources implem
      */
     private InstallationResources download(final String authority) throws 
IOException {
         final String source = getDownloadURL(authority);
-        final URLClassLoader loader = new URLClassLoader(new URL[] {new 
URL(source)});
+        final URLClassLoader loader;
+        try {
+            loader = new URLClassLoader(new URL[] {new URI(source).toURL()});
+        } catch (URISyntaxException e) {
+            throw (MalformedURLException) new 
MalformedURLException().initCause(e);
+        }
         for (final InstallationResources c : 
ServiceLoader.load(InstallationResources.class, loader)) {
             if (!c.getClass().isAnnotationPresent(Fallback.class) && 
c.getAuthorities().contains(authority)) {
                 return c;
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/io/OptionalDataDownloader.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/io/OptionalDataDownloader.java
index f73d5e6048..0636f723b2 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/io/OptionalDataDownloader.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/io/OptionalDataDownloader.java
@@ -16,11 +16,13 @@
  */
 package org.apache.sis.gui.internal.io;
 
+import java.util.Set;
 import javafx.application.Platform;
 import javafx.scene.control.Alert;
 import javafx.scene.control.ButtonType;
 import javafx.scene.control.DialogPane;
 import javafx.scene.web.WebView;
+import java.awt.GraphicsEnvironment;
 import org.opengis.util.FactoryException;
 import org.apache.sis.gui.DataViewer;
 import org.apache.sis.gui.internal.BackgroundThreads;
@@ -55,6 +57,19 @@ public final class OptionalDataDownloader extends 
OptionalInstallations {
         super("text/html");
     }
 
+    /**
+     * Returns the name of the authority who provides data under non-Apache 
terms of use.
+     * If this {@code OptionalDataDownloader} cannot ask user's agreement 
because the
+     * environment {@linkplain GraphicsEnvironment#isHeadless() is headless},
+     * then this method returns an empty set.
+     *
+     * @return {@code "EPSG"} or an empty set in this class cannot ask user's 
agreement.
+     */
+    @Override
+    public Set<String> getAuthorities() {
+        return GraphicsEnvironment.isHeadless() ? Set.of(): 
super.getAuthorities();
+    }
+
     /**
      * Asks to the user if (s)he agree to download and install the resource 
for the given authority.
      * This method may be invoked twice for the same {@code authority} 
argument:
diff --git 
a/optional/src/org.apache.sis.referencing.database/test/org/apache/sis/resources/embedded/EmbeddedResourcesTest.java
 
b/optional/src/org.apache.sis.referencing.database/test/org/apache/sis/resources/embedded/EmbeddedResourcesTest.java
index 43a300a918..6dee0b4fbb 100644
--- 
a/optional/src/org.apache.sis.referencing.database/test/org/apache/sis/resources/embedded/EmbeddedResourcesTest.java
+++ 
b/optional/src/org.apache.sis.referencing.database/test/org/apache/sis/resources/embedded/EmbeddedResourcesTest.java
@@ -76,7 +76,6 @@ public final strictfp class EmbeddedResourcesTest {
         } catch (Exception e) {
             throw new AssertionError(e);
         }
-
         InstallationResources provider = null;
         for (InstallationResources candidate : 
ServiceLoader.load(InstallationResources.class)) {
             if (candidate instanceof EmbeddedResources) {

Reply via email to