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) {