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 6d1043d6839d9c534fa565a47e97955dbaaf4abe Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Mon Nov 27 11:59:04 2023 +0100 When opening files in a folder, inherit the options specified in the parent `StorageConnector`. --- .../org/apache/sis/storage/StorageConnector.java | 35 ++++++++++++---- .../main/org/apache/sis/storage/folder/Store.java | 46 ++++++++++------------ .../apache/sis/storage/folder/WritableStore.java | 5 +-- 3 files changed, 48 insertions(+), 38 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 7d48090aee..708d431156 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 @@ -17,6 +17,7 @@ package org.apache.sis.storage; import java.util.Map; +import java.util.HashMap; import java.util.Iterator; import java.util.IdentityHashMap; import java.util.function.UnaryOperator; @@ -55,9 +56,11 @@ import org.apache.sis.util.ObjectConverters; import org.apache.sis.util.UnconvertibleObjectException; import org.apache.sis.util.resources.Errors; import org.apache.sis.util.logging.Logging; +import org.apache.sis.util.internal.Strings; import org.apache.sis.util.collection.TreeTable; import org.apache.sis.util.collection.TableColumn; import org.apache.sis.util.collection.DefaultTreeTable; +import org.apache.sis.util.collection.Containers; import org.apache.sis.storage.internal.Resources; import org.apache.sis.storage.base.StoreUtilities; import org.apache.sis.io.InvalidSeekException; @@ -72,7 +75,6 @@ import org.apache.sis.io.stream.InputStreamAdapter; import org.apache.sis.io.stream.RewindableLineReader; import org.apache.sis.io.stream.InternalOptionKey; import org.apache.sis.system.Configuration; -import org.apache.sis.util.internal.Strings; import org.apache.sis.setup.OptionKey; @@ -623,15 +625,19 @@ public class StorageConnector implements Serializable { } /** - * Returns the option value for the given key, or {@code null} if none. + * Creates a new data store connection which has a sub-component of a larger data store. + * The new storage connector inherits all options that were specified in the parent connector. * - * @param <T> the type of option value. - * @param key the option for which to get the value. - * @return the current value for the given option, or {@code null} if none. + * @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>. + * + * @since 1.5 */ - public <T> T getOption(final OptionKey<T> key) { - ArgumentChecks.ensureNonNull("key", key); - return key.getValueFrom(options); + public StorageConnector(final StorageConnector parent, final Object storage) { + this(storage); + if (!Containers.isNullOrEmpty(parent.options)) { + options = new HashMap<>(parent.options); + } } /** @@ -653,6 +659,19 @@ public class StorageConnector implements Serializable { options = key.setValueInto(options, value); } + /** + * Returns the option value for the given key, or {@code null} if none. + * This is the value specified by the last call to a {@code setOption(…)} with the given key. + * + * @param <T> the type of option value. + * @param key the option for which to get the value. + * @return the current value for the given option, or {@code null} if none. + */ + public <T> T getOption(final OptionKey<T> key) { + ArgumentChecks.ensureNonNull("key", key); + return key.getValueFrom(options); + } + /** * Returns the input/output object given at construction time. * The object can be of any type, but the class javadoc lists the most typical ones. diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/Store.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/Store.java index af69ac87f5..f6821a7fd4 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/Store.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/Store.java @@ -32,6 +32,7 @@ import java.nio.file.Path; import java.nio.file.Files; import java.nio.file.DirectoryStream; import java.nio.file.DirectoryIteratorException; +import java.nio.file.StandardOpenOption; import org.opengis.util.GenericName; import org.opengis.util.NameFactory; import org.opengis.util.NameSpace; @@ -99,19 +100,10 @@ class Store extends DataStore implements StoreResource, UnstructuredAggregate, D private GenericName identifier; /** - * Formatting conventions of dates and numbers, or {@code null} if unspecified. + * The user-specified connector of the root directory. + * Used for inheriting options when creating connector for components. */ - protected final Locale locale; - - /** - * Timezone of dates in the data store, or {@code null} if unspecified. - */ - protected final TimeZone timezone; - - /** - * Character encoding used by the data store, or {@code null} if unspecified. - */ - protected final Charset encoding; + protected final StorageConnector configuration; /** * All data stores (including sub-folders) found in the directory structure, including the root directory. @@ -173,12 +165,10 @@ class Store extends DataStore implements StoreResource, UnstructuredAggregate, D throws DataStoreException, IOException { super(provider, connector); - originator = this; - location = path; - locale = connector.getOption(OptionKey.LOCALE); - timezone = connector.getOption(OptionKey.TIMEZONE); - encoding = connector.getOption(OptionKey.ENCODING); - children = new ConcurrentHashMap<>(); + configuration = connector; + originator = this; + location = path; + children = new ConcurrentHashMap<>(); children.put(path.toRealPath(), this); componentProvider = format; } @@ -192,10 +182,8 @@ class Store extends DataStore implements StoreResource, UnstructuredAggregate, D */ private Store(final Store parent, final StorageConnector connector, final NameFactory nameFactory) throws DataStoreException { super(parent, parent.getProvider(), connector, false); + configuration = parent.configuration; originator = parent; - locale = connector.getOption(OptionKey.LOCALE); - timezone = connector.getOption(OptionKey.TIMEZONE); - encoding = connector.getOption(OptionKey.ENCODING); location = connector.commit(Path.class, StoreProvider.NAME); children = parent.children; componentProvider = parent.componentProvider; @@ -218,6 +206,9 @@ class Store extends DataStore implements StoreResource, UnstructuredAggregate, D final String format = StoreUtilities.getFormatName(componentProvider); final ParameterValueGroup pg = (provider != null ? provider.getOpenParameters() : StoreProvider.PARAMETERS).createValue(); pg.parameter(DataStoreProvider.LOCATION).setValue(location); + Locale locale = configuration.getOption(OptionKey.LOCALE); + TimeZone timezone = configuration.getOption(OptionKey.TIMEZONE); + Charset encoding = configuration.getOption(OptionKey.ENCODING); if (locale != null) pg.parameter("locale" ).setValue(locale ); if (timezone != null) pg.parameter("timezone").setValue(timezone); if (encoding != null) pg.parameter("encoding").setValue(encoding); @@ -270,7 +261,10 @@ class Store extends DataStore implements StoreResource, UnstructuredAggregate, D if (metadata == null) { final MetadataBuilder mb = new MetadataBuilder(); mb.addResourceScope(ScopeCode.COLLECTION, Resources.formatInternational(Resources.Keys.DirectoryContent_1, getDisplayName())); - mb.addLanguage(locale, encoding, MetadataBuilder.Scope.RESOURCE); + mb.addLanguage(configuration.getOption(OptionKey.LOCALE), + configuration.getOption(OptionKey.ENCODING), + MetadataBuilder.Scope.RESOURCE); + final GenericName identifier = identifier(null); String name = null; if (identifier != null) { @@ -320,11 +314,11 @@ class Store extends DataStore implements StoreResource, UnstructuredAggregate, D * If the file format is unknown (UnsupportedStorageException), we will * check if we can open it as a child folder store before to skip it. */ - final StorageConnector connector = new StorageConnector(candidate); - connector.setOption(OptionKey.LOCALE, locale); - connector.setOption(OptionKey.TIMEZONE, timezone); - connector.setOption(OptionKey.ENCODING, encoding); + final StorageConnector connector = new StorageConnector(configuration, candidate); connector.setOption(DataOptionKey.PARENT_LISTENERS, listeners); + connector.setOption(OptionKey.OPEN_OPTIONS, new StandardOpenOption[] { + StandardOpenOption.READ // Restrict to read-only mode. + }); try { if (componentProvider == null) { next = DataStores.open(connector); // May throw UnsupportedStorageException. diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/WritableStore.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/WritableStore.java index 4f4f94a91c..1f9f65e780 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/WritableStore.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/WritableStore.java @@ -107,10 +107,7 @@ final class WritableStore extends Store implements WritableAggregate { */ final Path path = location.resolve(filename); if (!children.containsKey(path)) { - final StorageConnector connector = new StorageConnector(path); - connector.setOption(OptionKey.LOCALE, locale); - connector.setOption(OptionKey.TIMEZONE, timezone); - connector.setOption(OptionKey.ENCODING, encoding); + final StorageConnector connector = new StorageConnector(configuration, path); connector.setOption(OptionKey.OPEN_OPTIONS, new StandardOpenOption[] { StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE });