Clarification about whether a DataStore.getFoo() method can return null.
Contain one last-minute API change before 1.0 release: getOpenParameters() return Optional.
diff --git a/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatStore.java b/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatStore.java
index 02bcaf6..770b330 100644
--- a/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatStore.java
+++ b/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatStore.java
@@ -20,6 +20,7 @@
 import java.io.BufferedReader;
 import java.io.LineNumberReader;
 import java.io.IOException;
+import java.nio.file.StandardOpenOption;
 import java.net.URI;
 import java.util.Optional;
 import org.opengis.metadata.Metadata;
@@ -28,6 +29,7 @@
 import org.opengis.parameter.ParameterValueGroup;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.DataStoreClosedException;
 import org.apache.sis.storage.DataStoreReferencingException;
 import org.apache.sis.storage.UnsupportedStorageException;
 import org.apache.sis.storage.StorageConnector;
@@ -114,18 +116,18 @@
 
     /**
      * Returns the parameters used to open this Landsat data store.
-     * If non-null, the parameters are described by {@link LandsatStoreProvider#getOpenParameters()} and contains at
-     * least a parameter named {@value org.apache.sis.storage.DataStoreProvider#LOCATION} with a {@link URI} value.
-     * This method may return {@code null} if the storage input can not be described by a URI
+     * The parameters are described by {@link LandsatStoreProvider#getOpenParameters()} and contains at least
+     * a parameter named {@value org.apache.sis.storage.DataStoreProvider#LOCATION} with a {@link URI} value.
+     * The return value may be empty if the storage input can not be described by a URI
      * (for example a Landsat file reading directly from a {@link java.nio.channels.ReadableByteChannel}).
      *
-     * @return parameters used for opening this data store, or {@code null} if not available.
+     * @return parameters used for opening this data store.
      *
      * @since 0.8
      */
     @Override
-    public ParameterValueGroup getOpenParameters() {
-        return URIDataStore.parameters(provider, location);
+    public Optional<ParameterValueGroup> getOpenParameters() {
+        return Optional.ofNullable(URIDataStore.parameters(provider, location));
     }
 
     /**
@@ -156,17 +158,20 @@
      */
     @Override
     public synchronized Metadata getMetadata() throws DataStoreException {
-        if (metadata == null && source != null) try {
+        if (metadata == null) {
+            if (source == null) {
+                throw new DataStoreClosedException(getLocale(), LandsatStoreProvider.NAME, StandardOpenOption.READ);
+            }
             try (BufferedReader reader = (source instanceof BufferedReader) ? (BufferedReader) source : new LineNumberReader(source)) {
                 source = null;      // Will be closed at the end of this try-finally block.
                 final LandsatReader parser = new LandsatReader(getDisplayName(), listeners);
                 parser.read(reader);
                 metadata = parser.getMetadata();
+            } catch (IOException e) {
+                throw new DataStoreException(e);
+            } catch (FactoryException e) {
+                throw new DataStoreReferencingException(e);
             }
-        } catch (IOException e) {
-            throw new DataStoreException(e);
-        } catch (FactoryException e) {
-            throw new DataStoreReferencingException(e);
         }
         return metadata;
     }
diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java
index d6e1b25..d8175b6 100644
--- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java
+++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java
@@ -154,16 +154,16 @@
 
     /**
      * Returns the parameters used to open this GeoTIFF data store.
-     * If non-null, the parameters are described by {@link GeoTiffStoreProvider#getOpenParameters()} and contains at
-     * least a parameter named {@value org.apache.sis.storage.DataStoreProvider#LOCATION} with a {@link URI} value.
-     * This method may return {@code null} if the storage input can not be described by a URI
+     * The parameters are described by {@link GeoTiffStoreProvider#getOpenParameters()} and contains at least
+     * a parameter named {@value org.apache.sis.storage.DataStoreProvider#LOCATION} with a {@link URI} value.
+     * The return value may be empty if the storage input can not be described by a URI
      * (for example a GeoTIFF file reading directly from a {@link java.nio.channels.ReadableByteChannel}).
      *
-     * @return parameters used for opening this data store, or {@code null} if not available.
+     * @return parameters used for opening this data store.
      */
     @Override
-    public ParameterValueGroup getOpenParameters() {
-        return URIDataStore.parameters(provider, location);
+    public Optional<ParameterValueGroup> getOpenParameters() {
+        return Optional.ofNullable(URIDataStore.parameters(provider, location));
     }
 
     /**
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
index 6094911..afaf805 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
@@ -129,13 +129,13 @@
      * This method may return {@code null} if the storage input can not be described by a URI
      * (for example a netCDF file reading directly from a {@link java.nio.channels.ReadableByteChannel}).
      *
-     * @return parameters used for opening this data store, or {@code null} if not available.
+     * @return parameters used for opening this data store.
      *
      * @since 0.8
      */
     @Override
-    public ParameterValueGroup getOpenParameters() {
-        return URIDataStore.parameters(provider, location);
+    public Optional<ParameterValueGroup> getOpenParameters() {
+        return Optional.ofNullable(URIDataStore.parameters(provider, location));
     }
 
     /**
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/storage/sql/SQLStore.java b/storage/sis-sqlstore/src/main/java/org/apache/sis/storage/sql/SQLStore.java
index 83acbd3..b22b6d2 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/storage/sql/SQLStore.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/storage/sql/SQLStore.java
@@ -135,14 +135,14 @@
      * @return parameters used for opening this data store.
      */
     @Override
-    public ParameterValueGroup getOpenParameters() {
+    public Optional<ParameterValueGroup> getOpenParameters() {
         if (provider == null) {
-            return null;
+            return Optional.empty();
         }
         final ParameterValueGroup pg = provider.getOpenParameters().createValue();
         pg.parameter(SQLStoreProvider.LOCATION).setValue(source);
         pg.parameter(SQLStoreProvider.TABLES).setValue(tableNames);
-        return pg;
+        return Optional.of(pg);
     }
 
     /**
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java
index 26525c3..069e503 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java
@@ -17,6 +17,7 @@
 package org.apache.sis.internal.storage;
 
 import java.net.URI;
+import java.util.Optional;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.FileSystemNotFoundException;
@@ -103,11 +104,11 @@
     /**
      * Returns the parameters used to open this data store.
      *
-     * @return parameters used for opening this {@code DataStore}, or {@code null} if not available.
+     * @return parameters used for opening this {@code DataStore}.
      */
     @Override
-    public ParameterValueGroup getOpenParameters() {
-        return parameters(provider, location);
+    public Optional<ParameterValueGroup> getOpenParameters() {
+        return Optional.ofNullable(parameters(provider, location));
     }
 
     /**
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/Store.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/Store.java
index eb9a6c0..df63841 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/Store.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/Store.java
@@ -210,7 +210,7 @@
      * Returns the parameters used to open this data store.
      */
     @Override
-    public ParameterValueGroup getOpenParameters() {
+    public Optional<ParameterValueGroup> getOpenParameters() {
         final String format = StoreUtilities.getFormatName(componentProvider);
         final ParameterValueGroup pg = (provider != null ? provider.getOpenParameters() : FolderStoreProvider.PARAMETERS).createValue();
         pg.parameter(DataStoreProvider.LOCATION).setValue(location);
@@ -218,7 +218,7 @@
         if (timezone != null) pg.parameter("timezone").setValue(timezone);
         if (encoding != null) pg.parameter("encoding").setValue(encoding);
         if (format   != null) pg.parameter("format"  ).setValue(format);
-        return pg;
+        return Optional.of(pg);
     }
 
     /**
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
index ab48a4d..475c50e 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
@@ -116,7 +116,7 @@
 
     /**
      * Creates a new instance for the given storage (typically file or database).
-     * The {@code provider} argument is an optional information.
+     * The {@code provider} argument is an optional but recommended information.
      * The {@code connector} argument is mandatory.
      *
      * @param  provider   the factory that created this {@code DataStore} instance, or {@code null} if unspecified.
@@ -170,6 +170,10 @@
      * The provider gives additional information on this {@code DataStore} such as a format description
      * and a list of parameters that can be used for opening data stores of the same class.
      *
+     * <p>The return value should never be null if this {@code DataStore} has been created by
+     * {@link DataStores#open(Object)} or by a {@link DataStoreProvider} {@code open(…)} method.
+     * However it may be null if this object has been instantiated by a direct call to its constructor.</p>
+     *
      * @return the factory that created this {@code DataStore} instance, or {@code null} if unspecified.
      *
      * @see #provider
@@ -193,15 +197,15 @@
      *
      * <p>In some cases, for stores reading in-memory data or other inputs that can not fit with
      * {@code ParameterDescriptorGroup} requirements (for example an {@link java.io.InputStream}
-     * connected to unknown or no {@link java.net.URL}), this method may return null.</p>
+     * connected to unknown or no {@link java.net.URL}), this method may return an empty value.</p>
      *
-     * @return parameters used for opening this {@code DataStore}, or {@code null} if not available.
+     * @return parameters used for opening this {@code DataStore}.
      *
      * @see DataStoreProvider#getOpenParameters()
      *
      * @since 0.8
      */
-    public abstract ParameterValueGroup getOpenParameters();
+    public abstract Optional<ParameterValueGroup> getOpenParameters();
 
     /**
      * Sets the locale to use for formatting warnings and other messages.
@@ -346,7 +350,7 @@
      * contact information about the creator or distributor, data quality, update frequency, usage constraints,
      * file format and more.
      *
-     * @return information about resources in the data store, or {@code null} if none.
+     * @return information about resources in the data store. Should not be {@code null}.
      * @throws DataStoreException if an error occurred while reading the data.
      *
      * @see #getIdentifier()
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
index fd206c5..d8091d3 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
@@ -199,7 +199,7 @@
      * <p>Implementers are responsible for declaring all parameters and whether they are mandatory or optional.
      * It is recommended to define at least a parameter named {@value #LOCATION}, completed by {@value #CREATE}
      * if the data store supports write operations.
-     * That parameter will be recognized by the default {@code DataStoreProvider} methods and used whenever a
+     * Those parameters will be recognized by the default {@code DataStoreProvider} methods and used whenever a
      * {@link StorageConnector} is required.</p>
      *
      * <div class="note"><b>Alternative:</b>
diff --git a/storage/sis-storage/src/test/java/org/apache/sis/storage/DataStoreMock.java b/storage/sis-storage/src/test/java/org/apache/sis/storage/DataStoreMock.java
index cbbce51..d14b8c5 100644
--- a/storage/sis-storage/src/test/java/org/apache/sis/storage/DataStoreMock.java
+++ b/storage/sis-storage/src/test/java/org/apache/sis/storage/DataStoreMock.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.storage;
 
+import java.util.Optional;
 import org.opengis.metadata.Metadata;
 import org.opengis.parameter.ParameterValueGroup;
 import org.apache.sis.storage.event.StoreListeners;
@@ -53,11 +54,11 @@
     }
 
     /**
-     * Returns {@code null} since there is no open parameters.
+     * Returns empty optional since there is no open parameters.
      */
     @Override
-    public ParameterValueGroup getOpenParameters() {
-        return null;
+    public Optional<ParameterValueGroup> getOpenParameters() {
+        return Optional.empty();
     }
 
     /**