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 f9c073b1c8158eaf27a017bb0ab2f45de4c38649 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Tue Jun 13 17:34:47 2023 +0200 Replace `TypeRegistration.hasRenameFile(…)` by a mechanism in which the `TypeRegistration` subclass fetches itself the resource. This is necessary in a context of Java module, because the resource can not be opened from `org.apache.sis.xml.Transformer`. --- .../apache/sis/internal/jaxb/TypeRegistration.java | 55 +++++++++++++--------- .../main/java/org/apache/sis/xml/Transformer.java | 16 +++---- .../sis/internal/profile/fra/ProfileTypes.java | 20 +++++--- 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java index fac23dd33c..e70df4e54f 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java @@ -16,7 +16,6 @@ */ package org.apache.sis.internal.jaxb; -import java.util.Set; import java.util.Map; import java.util.HashMap; import java.util.ArrayList; @@ -24,6 +23,10 @@ import java.util.Collection; import java.util.ServiceLoader; import java.util.concurrent.TimeUnit; import java.util.function.UnaryOperator; +import java.util.function.Supplier; +import java.util.Optional; +import java.util.Iterator; +import java.io.InputStream; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import jakarta.xml.bind.JAXBContext; @@ -39,10 +42,8 @@ import org.apache.sis.internal.system.DelayedRunnable; * Declares the classes of objects to be marshalled using a default {@code MarshallerPool}. * This class is not strictly necessary for marshalling a SIS object using JAXB, but makes * the job easier by allowing {@code MarshallerPool} to configure the JAXB context automatically. - * To allow such automatic configuration, modules must declare instances of this interface in the - * following file: - * - * <pre class="text">META-INF/services/org.org.apache.sis.internal.jaxb.TypeRegistration</pre> + * To allow such automatic configuration, modules must declare instances of this interface + * as a service in their {@code module-info}. * * @author Martin Desruisseaux (Geomatys) * @version 1.4 @@ -130,30 +131,42 @@ public abstract class TypeRegistration { } /** - * Returns {@code true} if {@code "RenameOnImport.lst"} and/or {@code "RenameOnExport.lst"} files are provided. - * If {@code true}, then those files shall be located in the same directory than this {@code TypeRegistration} - * subclass. + * Opens a stream on the {@code "RenameOnImport.lst"} or {@code "RenameOnExport.lst"} file if present. + * Those files are typically located in the same directory than this {@code TypeRegistration} subclass. + * + * <h4>Design note</h4> + * If a modularized project, the call to {@link Class#getResourceAsStream(String)} must be done in the + * module which contains the resource. It is not possible to only request the filename and open the + * resources in this metadata module. * - * @param export {@code true} for {@code "RenameOnImport.lst"}, {@code false} for {@code "RenameOnImport.lst"}. - * @return whether {@code "RenameOnImport.lst"} and/or {@code "RenameOnExport.lst"} files are provided. + * @param export {@code true} for {@code "RenameOnExport.lst"}, {@code false} for {@code "RenameOnImport.lst"}. + * @param filename the filename as documented in the {@code export} argument, for convenience. + * @return stream opened on the {@code "RenameOnImport.lst"} or the {@code "RenameOnExport.lst"} file. */ - protected boolean hasRenameFile(boolean export) { - return false; + protected Optional<InputStream> getRenameDefinitionsFile(boolean export, String filename) { + return Optional.empty(); } /** - * Adds in the given set the classes to use for loading {@code "RenameOnImport.lst"} and/or {@code "RenameOnExport.lst"} files. - * The given set should preserve insertion order, since the order in which files are loaded may matter. + * Returns all input streams for loading the {@code "RenameOnImport.lst"} or {@code "RenameOnExport.lst"} file. + * Each stream will be opened only when requested. The supplier returns {@code null} after the last stream has + * been returned. * - * @param export {@code true} for {@code "RenameOnImport.lst"}, {@code false} for {@code "RenameOnImport.lst"}. - * @param addTo where to add the classes to use for loading the resource files. + * @param export {@code true} for {@code "RenameOnExport.lst"}, {@code false} for {@code "RenameOnImport.lst"}. + * @param filename the filename as documented in the {@code export} argument, for convenience. + * @return all input streams. */ - public static synchronized void getRenameFileLoader(final boolean export, final Set<Class<?>> addTo) { - for (final TypeRegistration t : services()) { - if (t.hasRenameFile(export)) { - addTo.add(t.getClass()); + public static synchronized Supplier<InputStream> getRenameDefinitionsFiles(final boolean export, final String filename) { + final Iterator<TypeRegistration> services = services().iterator(); + return () -> { + synchronized (TypeRegistration.class) { + while (services.hasNext()) { + final Optional<InputStream> next = services.next().getRenameDefinitionsFile(export, filename); + if (next.isPresent()) return next.get(); + } + return null; } - } + }; } /** diff --git a/core/sis-metadata/src/main/java/org/apache/sis/xml/Transformer.java b/core/sis-metadata/src/main/java/org/apache/sis/xml/Transformer.java index b84bf47585..8cf53ae2fa 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/xml/Transformer.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/Transformer.java @@ -19,12 +19,13 @@ package org.apache.sis.xml; import java.util.Map; import java.util.HashMap; import java.util.Set; -import java.util.LinkedHashSet; import java.util.List; import java.util.Arrays; import java.util.ArrayList; import java.util.InvalidPropertiesFormatException; +import java.util.function.Supplier; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; import javax.xml.XMLConstants; @@ -83,7 +84,7 @@ import org.apache.sis.internal.jaxb.TypeRegistration; * * @author Martin Desruisseaux (Geomatys) * @author Cullen Rombach (Image Matters) - * @version 1.0 + * @version 1.4 * * @see javax.xml.transform.Transformer * @@ -242,11 +243,10 @@ abstract class Transformer { */ static Map<String, Map<String,String>> load(final boolean export, final String filename, final Set<String> targets, final int capacity) { final Map<String, Map<String,String>> m = new HashMap<>(capacity); - final Set<Class<?>> renameLoaders = new LinkedHashSet<>(8); - renameLoaders.add(Transformer.class); - TypeRegistration.getRenameFileLoader(export, renameLoaders); - for (final Class<?> loader : renameLoaders) { - try (LineNumberReader in = new LineNumberReader(new InputStreamReader(loader.getResourceAsStream(filename), "UTF-8"))) { + final Supplier<InputStream> plugins = TypeRegistration.getRenameDefinitionsFiles(export, filename); + InputStream resourceStream = Transformer.class.getResourceAsStream(filename); + do { + try (LineNumberReader in = new LineNumberReader(new InputStreamReader(resourceStream, "UTF-8"))) { Map<String,String> attributes = null; // All attributes for a given type. String namespace = null; // Value to store in `attributes` map. String line; @@ -358,7 +358,7 @@ abstract class Transformer { } catch (IOException e) { throw new ExceptionInInitializerError(e); } - } + } while ((resourceStream = plugins.get()) != null); /* * At this point we finished computing the map values. Many values are maps with only 1 entry. */ diff --git a/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java b/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java index 65706a5151..dc1519721e 100644 --- a/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java +++ b/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java @@ -16,7 +16,9 @@ */ package org.apache.sis.internal.profile.fra; +import java.io.InputStream; import java.util.Collection; +import java.util.Optional; import org.apache.sis.internal.jaxb.TypeRegistration; @@ -25,7 +27,7 @@ import org.apache.sis.internal.jaxb.TypeRegistration; * This class is declared in the {@code META-INF/services/org.apache.sis.internal.jaxb.TypeRegistration} file. * * @author Martin Desruisseaux (Geomatys) - * @version 1.0 + * @version 1.4 * @since 0.4 */ public final class ProfileTypes extends TypeRegistration { @@ -43,14 +45,18 @@ public final class ProfileTypes extends TypeRegistration { } /** - * Returns {@code true} for {@code export = false} in order to notify that we provide - * a {@code "RenameOnImport.lst"} file that need to be read. + * Opens a stream on the {@code "RenameOnImport.lst"} if {@code export} is false. * - * @param export {@code true} for {@code "RenameOnImport.lst"}, {@code false} for {@code "RenameOnImport.lst"}. - * @return {@code true} for {@code "RenameOnImport.lst"}, {@code false} otherwise. + * @param export {@code false} for {@code "RenameOnImport.lst"}. + * @param filename a filename consistent with the {@code export} argument, for convenience. + * @return stream opened on the {@code "RenameOnImport.lst"} file if {@code export} is false. */ @Override - protected boolean hasRenameFile(boolean export) { - return !export; + protected Optional<InputStream> getRenameDefinitionsFile(final boolean export, final String filename) { + if (export) { + return super.getRenameDefinitionsFile(export, filename); + } else { + return Optional.of(ProfileTypes.class.getResourceAsStream(filename)); + } } }