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 a8fcd7a9fe484ee32c9fbcc275e3303517f5d997 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Thu Apr 14 20:11:28 2022 +0200 Implement `probleContent(…)` for World File data store. Fix documentation in other implementations of `probleContent(…)`. --- .../sis/storage/landsat/LandsatStoreProvider.java | 2 +- .../sis/storage/geotiff/GeoTiffStoreProvider.java | 11 +++--- .../sis/storage/netcdf/NetcdfStoreProvider.java | 11 +++--- .../apache/sis/storage/sql/SQLStoreProvider.java | 2 +- .../sis/internal/storage/ascii/StoreProvider.java | 12 ++++--- .../sis/internal/storage/csv/StoreProvider.java | 12 ++++--- .../sis/internal/storage/folder/StoreProvider.java | 4 +-- .../sis/internal/storage/image/FormatFilter.java | 42 +++++++++++++++++++++- .../apache/sis/internal/storage/image/Store.java | 5 ++- .../sis/internal/storage/image/StoreProvider.java | 36 +++++++++++++++++-- .../sis/internal/storage/wkt/StoreProvider.java | 20 +++++------ .../sis/internal/storage/xml/AbstractProvider.java | 13 +++---- .../org/apache/sis/storage/DataStoreProvider.java | 8 ++--- .../internal/storage/wkt/StoreProviderTest.java | 2 +- 14 files changed, 129 insertions(+), 51 deletions(-) diff --git a/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/landsat/LandsatStoreProvider.java b/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/landsat/LandsatStoreProvider.java index 448b3968b6..7be9c50b39 100644 --- a/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/landsat/LandsatStoreProvider.java +++ b/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/landsat/LandsatStoreProvider.java @@ -198,7 +198,7 @@ public class LandsatStoreProvider extends DataStoreProvider { * that there appears to be a reasonable chance of success based on a brief inspection of the storage header. * * @return {@link ProbeResult#SUPPORTED} if the given storage seems to be readable as a Landsat file. - * @throws DataStoreException if an I/O or SQL error occurred. + * @throws DataStoreException if an I/O error occurred. */ @Override public ProbeResult probeContent(final StorageConnector connector) throws DataStoreException { diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStoreProvider.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStoreProvider.java index f59ec4d1e7..5059e7b55b 100644 --- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStoreProvider.java +++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStoreProvider.java @@ -95,13 +95,14 @@ public class GeoTiffStoreProvider extends DataStoreProvider { } /** - * Returns {@link ProbeResult#SUPPORTED} if the given storage appears to be supported by {@link GeoTiffStore}. - * Returning {@code SUPPORTED} from this method does not guarantee that reading or writing will succeed, - * only that there appears to be a reasonable chance of success based on a brief inspection of the - * {@linkplain StorageConnector#getStorage() storage object} or contents. + * Returns the MIME type if the given storage appears to be supported by {@link GeoTiffStore}. + * A {@linkplain ProbeResult#isSupported() supported} status does not guarantee that reading + * or writing will succeed, only that there appears to be a reasonable chance of success + * based on a brief inspection of the file header. * * @param connector information about the storage (URL, stream, <i>etc</i>). - * @return {@code SUPPORTED} if the given storage seems to be usable by {@code GeoTiffStore} instances. + * @return a {@linkplain ProbeResult#isSupported() supported} status with the MIME type + * if the given storage seems to be readable by {@code GeoTiffStore} instances. * @throws DataStoreException if an I/O error occurred. */ @Override diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java index 7dd23ac87a..033d126fd4 100644 --- a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java +++ b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java @@ -176,13 +176,14 @@ public class NetcdfStoreProvider extends DataStoreProvider { } /** - * Returns {@link ProbeResult#SUPPORTED} if the given storage appears to be supported by {@link NetcdfStore}. - * Returning {@code SUPPORTED} from this method does not guarantee that reading or writing will succeed, - * only that there appears to be a reasonable chance of success based on a brief inspection of the - * {@linkplain StorageConnector#getStorage() storage object} or contents. + * Returns the MIME type if the given storage appears to be supported by {@link NetcdfStore}. + * A {@linkplain ProbeResult#isSupported() supported} status does not guarantee that reading + * or writing will succeed, only that there appears to be a reasonable chance of success + * based on a brief inspection of the file header. * * @param connector information about the storage (URL, stream, {@link ucar.nc2.NetcdfFile} instance, <i>etc</i>). - * @return {@code SUPPORTED} if the given storage seems to be usable by {@code NetcdfStore} instances. + * @return a {@linkplain ProbeResult#isSupported() supported} status with the MIME type + * if the given storage seems to be readable by {@code NetcdfStore} instances. * @throws DataStoreException if an I/O error occurred. */ @Override diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/storage/sql/SQLStoreProvider.java b/storage/sis-sqlstore/src/main/java/org/apache/sis/storage/sql/SQLStoreProvider.java index 8761c3a615..156289fb09 100644 --- a/storage/sis-sqlstore/src/main/java/org/apache/sis/storage/sql/SQLStoreProvider.java +++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/storage/sql/SQLStoreProvider.java @@ -175,7 +175,7 @@ public class SQLStoreProvider extends DataStoreProvider { * * @param connector information about the storage (data source). * @return {@code SUPPORTED} if the given storage seems to be usable by {@code SQLStore} instances. - * @throws DataStoreException if an I/O error occurred. + * @throws DataStoreException if an SQL error occurred. */ @Override public ProbeResult probeContent(final StorageConnector connector) throws DataStoreException { diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ascii/StoreProvider.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ascii/StoreProvider.java index a77dbaf7de..7e625150c9 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ascii/StoreProvider.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ascii/StoreProvider.java @@ -69,12 +69,14 @@ public final class StoreProvider extends PRJDataStore.Provider { } /** - * Returns {@link ProbeResult#SUPPORTED} if the given storage appears to be supported by ASCII Grid {@link Store}. - * Returning {@code SUPPORTED} from this method does not guarantee that reading or writing will succeed, only - * that there appears to be a reasonable chance of success based on a brief inspection of the storage header. + * Returns the MIME type if the given storage appears to be supported by ASCII Grid {@link Store}. + * A {@linkplain ProbeResult#isSupported() supported} status does not guarantee that reading + * or writing will succeed, only that there appears to be a reasonable chance of success + * based on a brief inspection of the file header. * - * @return {@link ProbeResult#SUPPORTED} if the given storage seems to be readable as an ASCII Grid file. - * @throws DataStoreException if an I/O or SQL error occurred. + * @return a {@linkplain ProbeResult#isSupported() supported} status with the MIME type + * if the given storage seems to be readable as an ASCII Grid file. + * @throws DataStoreException if an I/O error occurred. */ @Override public ProbeResult probeContent(StorageConnector connector) throws DataStoreException { diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java index b6ada7275d..d6a3db371a 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java @@ -143,12 +143,14 @@ public final class StoreProvider extends URIDataStore.Provider { } /** - * Returns {@link ProbeResult#SUPPORTED} if the given storage appears to be supported by CSV {@link Store}. - * Returning {@code SUPPORTED} from this method does not guarantee that reading or writing will succeed, only - * that there appears to be a reasonable chance of success based on a brief inspection of the storage header. + * Returns the MIME type if the given storage appears to be supported by CSV {@link Store}. + * A {@linkplain ProbeResult#isSupported() supported} status does not guarantee that reading + * or writing will succeed, only that there appears to be a reasonable chance of success + * based on a brief inspection of the file header. * - * @return {@link ProbeResult#SUPPORTED} if the given storage seems to be readable as a CSV file. - * @throws DataStoreException if an I/O or SQL error occurred. + * @return a {@linkplain ProbeResult#isSupported() supported} status with the MIME type + * if the given storage seems to be readable as a CSV file. + * @throws DataStoreException if an I/O error occurred. */ @Override public ProbeResult probeContent(final StorageConnector connector) throws DataStoreException { diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/StoreProvider.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/StoreProvider.java index 2f81fac1c2..f3906223b4 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/StoreProvider.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/StoreProvider.java @@ -146,10 +146,10 @@ public final class StoreProvider extends DataStoreProvider { * Returns {@link ProbeResult#SUPPORTED} if the given storage appears to be a folder. * Returning {@code SUPPORTED} from this method does not guarantee that reading or writing will succeed, * only that there appears to be a reasonable chance of success based on a brief inspection of the storage - * header. + * characteristics. * * @return {@link ProbeResult#SUPPORTED} if the given storage seems to be readable as a folder. - * @throws DataStoreException if an I/O or SQL error occurred. + * @throws DataStoreException if an I/O error occurred. */ @Override public ProbeResult probeContent(StorageConnector connector) throws DataStoreException { diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/FormatFilter.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/FormatFilter.java index 603852c9ab..610c34eed0 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/FormatFilter.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/FormatFilter.java @@ -17,6 +17,7 @@ package org.apache.sis.internal.storage.image; import java.util.Map; +import java.util.Set; import java.util.Iterator; import java.util.function.Function; import java.net.URI; @@ -119,6 +120,44 @@ enum FormatFilter { } } + /** + * Finds a provider for the given input, or returns {@code null} if none. + * + * @param identifier the property value to use as a filtering criterion, or {@code null} if none. + * @param connector provider of the input to be given to the {@code canDecodeInput(…)} method. + * @param done initially empty set to be populated with providers tested by this method. + * @return the provider for the given input, or {@code null} if none was found. + * @throws DataStoreException if an error occurred while opening a stream from the storage connector. + * @throws IOException if an error occurred while creating the image reader instance. + */ + final ImageReaderSpi findProvider(final String identifier, final StorageConnector connector, final Set<ImageReaderSpi> done) + throws IOException, DataStoreException + { + final Iterator<ImageReaderSpi> it = FormatFilter.SUFFIX.getServiceProviders(ImageReaderSpi.class, identifier); + while (it.hasNext()) { + final ImageReaderSpi provider = it.next(); + if (done.add(provider)) { + for (final Class<?> type : provider.getInputTypes()) { + if (Classes.isAssignableToAny(type, VALID_INPUTS)) { + final Object input = connector.getStorageAs(type); + if (input != null) { + /* + * We do not try to mark/reset the input because it should be done + * by `canDecodeInput(…)` as per Image I/O contract. Doing our own + * mark/reset may interfere with the `canDecodeInput(…)` marks. + */ + if (provider.canDecodeInput(input)) { + return provider; + } + break; // Skip other input types, try the next provider. + } + } + } + } + } + return null; + } + /** * Creates a new reader for the given input. Caller needs to invoke this method with an initially empty * {@code deferred} map, which will be populated by this method. Providers associated to {@code TRUE} @@ -126,7 +165,7 @@ enum FormatFilter { * This is intentionally not done automatically by {@link StorageConnector}. * * @param identifier the property value to use as a filtering criterion, or {@code null} if none. - * @param input the input to be given to the new reader instance. + * @param connector provider of the input to be given to the new reader instance. * @param deferred initially empty map to be populated with providers tested by this method. * @return the new image reader instance with its input initialized, or {@code null} if none was found. * @throws DataStoreException if an error occurred while opening a stream from the storage connector. @@ -149,6 +188,7 @@ enum FormatFilter { reader.setInput(input, false, true); return reader; } + break; // Skip other input types, try the next provider. } else if (type == ImageInputStream.class) { deferred.put(provider, Boolean.TRUE); } diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Store.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Store.java index 148c7f50d7..1a5510b1fc 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Store.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Store.java @@ -342,7 +342,10 @@ loop: for (int convention=0;; convention++) { public synchronized Metadata getMetadata() throws DataStoreException { if (metadata == null) try { final MetadataBuilder builder = new MetadataBuilder(); - final String format = reader().getFormatName(); + String format = reader().getFormatName(); + if (format.equalsIgnoreCase("tif")) { + format = "TIFF"; + } try { builder.setPredefinedFormat(format); } catch (MetadataStoreException e) { diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/StoreProvider.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/StoreProvider.java index 795e6fe4bb..435264a72d 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/StoreProvider.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/StoreProvider.java @@ -16,13 +16,17 @@ */ package org.apache.sis.internal.storage.image; +import java.util.Set; +import java.util.HashSet; import java.io.IOException; +import javax.imageio.spi.ImageReaderSpi; import org.apache.sis.storage.DataStore; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.StorageConnector; import org.apache.sis.internal.storage.Capability; import org.apache.sis.internal.storage.StoreMetadata; import org.apache.sis.internal.storage.PRJDataStore; +import org.apache.sis.internal.storage.io.IOUtilities; import org.apache.sis.storage.ProbeResult; @@ -74,8 +78,36 @@ public final class StoreProvider extends PRJDataStore.Provider { } } + /** + * Returns the MIME type if the image file is recognized by an Image I/O reader. + * A {@linkplain ProbeResult#isSupported() supported} status does not guarantee that reading + * or writing will succeed, only that there appears to be a reasonable chance of success + * based on a brief inspection of the file header. + * + * @return a {@linkplain ProbeResult#isSupported() supported} status with the MIME type + * if the given storage seems to be readable as an image. + * @throws DataStoreException if an I/O error occurred. + */ @Override - public ProbeResult probeContent(StorageConnector connector) throws DataStoreException { - throw new UnsupportedOperationException("Not supported yet."); + public ProbeResult probeContent(final StorageConnector connector) throws DataStoreException { + final Set<ImageReaderSpi> deferred = new HashSet<>(); + final String suffix = IOUtilities.extension(connector.getStorage()); + ImageReaderSpi provider; + try { + provider = FormatFilter.SUFFIX.findProvider(suffix, connector, deferred); + if (provider == null) { + provider = FormatFilter.SUFFIX.findProvider(null, connector, deferred); + if (provider == null) { + return ProbeResult.UNSUPPORTED_STORAGE; + } + } + } catch (IOException e) { + throw new DataStoreException(e); + } + final String[] types = provider.getMIMETypes(); + if (types != null && types.length != 0) { + return new ProbeResult(true, types[0], null); + } + return ProbeResult.SUPPORTED; } } diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java index c8534e3d4a..c95ab0f519 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java @@ -47,11 +47,6 @@ public final class StoreProvider extends URIDataStore.Provider { */ static final String NAME = "WKT"; - /** - * The {@value} MIME type. - */ - public static final String MIME_TYPE = "application/wkt"; - /** * The object to use for verifying if the first keyword is a WKT one. * This object contains the set of recognized WKT keywords. @@ -139,7 +134,7 @@ public final class StoreProvider extends URIDataStore.Provider { } } if (keywords.contains(String.valueOf(keyword, 0, length))) { - return new ProbeResult(true, MIME_TYPE, Version.valueOf(version)); + return new ProbeResult(true, null, Version.valueOf(version)); } } return ProbeResult.UNSUPPORTED_STORAGE; @@ -163,13 +158,14 @@ public final class StoreProvider extends URIDataStore.Provider { } /** - * Returns {@link ProbeResult#SUPPORTED} if the given storage appears to be supported by WKT {@link Store}. - * Returning {@code SUPPORTED} from this method does not guarantee that reading or writing will succeed, - * only that there appears to be a reasonable chance of success based on a brief inspection of the storage - * header. + * Returns WKT version if the given storage appears to be supported by WKT {@link Store}. + * A {@linkplain ProbeResult#isSupported() supported} status does not guarantee that reading + * or writing will succeed, only that there appears to be a reasonable chance of success + * based on a brief inspection of the file header. * - * @return {@link ProbeResult#SUPPORTED} if the given storage seems to be readable as a WKT file. - * @throws DataStoreException if an I/O or SQL error occurred. + * @return a {@linkplain ProbeResult#isSupported() supported} status with the WKT version + * if the given storage seems to be readable as a WKT string. + * @throws DataStoreException if an I/O error occurred. */ @Override public ProbeResult probeContent(final StorageConnector connector) throws DataStoreException { diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/AbstractProvider.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/AbstractProvider.java index e0e646a275..101afc143e 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/AbstractProvider.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/AbstractProvider.java @@ -98,13 +98,14 @@ public abstract class AbstractProvider extends DocumentedStoreProvider { } /** - * Returns {@link ProbeResult#SUPPORTED} if the given storage appears to be supported by the data store. - * Returning {@code SUPPORTED} from this method does not guarantee that reading or writing will succeed, - * only that there appears to be a reasonable chance of success based on a brief inspection of the storage - * header. + * Returns the MIME type if the given storage appears to be supported by the data store. + * A {@linkplain ProbeResult#isSupported() supported} status does not guarantee that reading + * or writing will succeed, only that there appears to be a reasonable chance of success + * based on a brief inspection of the file header. * - * @return {@link ProbeResult#SUPPORTED} if the given storage seems to be readable as a XML file. - * @throws DataStoreException if an I/O or SQL error occurred. + * @return a {@linkplain ProbeResult#isSupported() supported} status with the MIME type + * if the given storage seems to be readable as a XML file. + * @throws DataStoreException if an I/O error occurred. */ @Override public ProbeResult probeContent(final StorageConnector connector) throws DataStoreException { 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 e2e9e96d7b..0a6daee728 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 @@ -239,8 +239,8 @@ public abstract class DataStoreProvider { * with the format. The most typical return values are: * * <ul> - * <li>{@link ProbeResult#SUPPORTED} if the {@code DataStore}s created by this provider - * can open the given storage.</li> + * <li>{@link ProbeResult#SUPPORTED} or another instance with {@linkplain ProbeResult#isSupported() supported} + * status if the {@code DataStore}s created by this provider can open the given storage.</li> * <li>{@link ProbeResult#UNSUPPORTED_STORAGE} if the given storage does not appear to be in a format * supported by this {@code DataStoreProvider}.</li> * </ul> @@ -259,8 +259,8 @@ public abstract class DataStoreProvider { * </div> * * @param connector information about the storage (URL, stream, JDBC connection, <i>etc</i>). - * @return {@link ProbeResult#SUPPORTED} if the given storage seems to be readable by the {@code DataStore} - * instances created by this provider. + * @return a {@linkplain ProbeResult#isSupported() supported} status if the given storage + * seems to be readable by the {@code DataStore} instances created by this provider. * @throws DataStoreException if an I/O or SQL error occurred. The error shall be unrelated to the logical * structure of the storage. */ diff --git a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreProviderTest.java b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreProviderTest.java index ba74e61df7..f0067145b9 100644 --- a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreProviderTest.java +++ b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreProviderTest.java @@ -83,7 +83,7 @@ public final strictfp class StoreProviderTest extends TestCase { c.closeAllExcept(null); assertEquals("isSupported", isSupported, r.isSupported()); if (isSupported) { - assertEquals("mimeType", "application/wkt", r.getMimeType()); + assertNull ("mimeType", r.getMimeType()); assertEquals("version", version, r.getVersion().getMajor()); } }