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 d7e30273d6f42ef50338276a43fbad97426c64fa Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Wed Feb 26 12:41:22 2025 +0100 Support `ChannelImageInputStream` (internal class). This is needed for data stores that do a mix of own work and work delegated to Image I/O. --- .../org/apache/sis/storage/StorageConnector.java | 71 ++++++++++++++++------ .../apache/sis/storage/StorageConnectorTest.java | 16 +++++ 2 files changed, 67 insertions(+), 20 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 b851d8b821..da17522954 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 @@ -224,20 +224,21 @@ public class StorageConnector implements Serializable { */ private static final Map<Class<?>, Opener<?>> OPENERS = new IdentityHashMap<>(16); static { - add(String.class, StorageConnector::createString); - add(ByteBuffer.class, StorageConnector::createByteBuffer); - add(DataInput.class, StorageConnector::createDataInput); - add(DataOutput.class, StorageConnector::createDataOutput); - add(ImageInputStream.class, StorageConnector::createImageInputStream); - add(ImageOutputStream.class, StorageConnector::createImageOutputStream); - add(InputStream.class, StorageConnector::createInputStream); - add(OutputStream.class, StorageConnector::createOutputStream); - add(Reader.class, StorageConnector::createReader); - add(DataSource.class, StorageConnector::createDataSource); - add(Connection.class, StorageConnector::createConnection); - add(ChannelDataInput.class, StorageConnector::createChannelDataInput); // Undocumented case (SIS internal) - add(ChannelDataOutput.class, StorageConnector::createChannelDataOutput); // Undocumented case (SIS internal) - add(ChannelFactory.class, (s) -> null); // Undocumented. Shall not cache. + add(String.class, StorageConnector::createString); + add(ByteBuffer.class, StorageConnector::createByteBuffer); + add(DataInput.class, StorageConnector::createDataInput); + add(DataOutput.class, StorageConnector::createDataOutput); + add(ImageInputStream.class, StorageConnector::createImageInputStream); + add(ImageOutputStream.class, StorageConnector::createImageOutputStream); + add(InputStream.class, StorageConnector::createInputStream); + add(OutputStream.class, StorageConnector::createOutputStream); + add(Reader.class, StorageConnector::createReader); + add(DataSource.class, StorageConnector::createDataSource); + add(Connection.class, StorageConnector::createConnection); + add(ChannelDataInput.class, StorageConnector::createChannelDataInput); // Undocumented case (SIS internal) + add(ChannelDataOutput.class, StorageConnector::createChannelDataOutput); // Undocumented case (SIS internal) + add(ChannelImageInputStream.class, StorageConnector::createChannelImageInputStream); // Undocumented case (SIS internal) + add(ChannelFactory.class, (s) -> null); // Undocumented. Shall not cache. /* * ChannelFactory may have been created as a side effect of creating a ReadableByteChannel. * Caller should have asked for another type (e.g. InputStream) before to ask for that type. @@ -1081,7 +1082,7 @@ public class StorageConnector implements Serializable { * This method is one of the {@link #OPENERS} methods and should be invoked at most once per * {@code StorageConnector} instance. * - * @return input channel, or {@code null} if none or if {@linkplain #probing} result has been determined offline. + * @return input channel, or {@code null} if none or if {@linkplain #probing} result has been determined externally. * @throws IOException if an error occurred while opening a channel for the input. * * @see #createChannelDataOutput() @@ -1150,7 +1151,7 @@ public class StorageConnector implements Serializable { * <p>This method is one of the {@link #OPENERS} methods and should be invoked at most once per * {@code StorageConnector} instance.</p> * - * @return input stream, or {@code null} if none or if {@linkplain #probing} result has been determined offline. + * @return input stream, or {@code null} if none or if {@linkplain #probing} result has been determined externally. * @throws IOException if an error occurred while opening a stream for the input. * * @see #createDataOutput() @@ -1325,6 +1326,35 @@ public class StorageConnector implements Serializable { return false; } + /** + * Creates an {@link ChannelImageInputStream} from the {@link ChannelDataInput} if possible. + * This method is one of the {@link #OPENERS} methods and should be invoked at most once per + * {@code StorageConnector} instance. + * + * @return input stream, or {@code null} if none or if {@linkplain #probing} result has been determined externally. + */ + private ChannelImageInputStream createChannelImageInputStream() throws IOException, DataStoreException { + final Coupled c; + final ChannelImageInputStream asImageInput; + ChannelDataInput input = getStorageAs(ChannelDataInput.class); + if (input != null) { + c = getView(ChannelDataInput.class); + if (input instanceof ChannelImageInputStream) { + asImageInput = (ChannelImageInputStream) input; + } else { + asImageInput = new ChannelImageInputStream(input); + c.view = asImageInput; // Upgrade existing instance for all views. + } + } else { + if (!wasProbingAbsentFile()) { + addView(ChannelImageInputStream.class, null); // Remember that there is no view. + } + return null; + } + views.put(ChannelImageInputStream.class, c); // Share the same `Coupled` instance. + return asImageInput; + } + /** * Creates an {@link ImageInputStream} from the {@link DataInput} if possible. This method casts * {@code DataInput} if such cast is allowed, or upgrades {@link ChannelDataInput} implementation. @@ -1332,7 +1362,7 @@ public class StorageConnector implements Serializable { * <p>This method is one of the {@link #OPENERS} methods and should be invoked at most once per * {@code StorageConnector} instance.</p> * - * @return input stream, or {@code null} if none or if {@linkplain #probing} result has been determined offline. + * @return input stream, or {@code null} if none or if {@linkplain #probing} result has been determined externally. */ private ImageInputStream createImageInputStream() throws IOException, DataStoreException { final Coupled c; @@ -1375,7 +1405,7 @@ public class StorageConnector implements Serializable { * <p>This method is one of the {@link #OPENERS} methods and should be invoked at most once per * {@code StorageConnector} instance.</p> * - * @return input stream, or {@code null} if none or if {@linkplain #probing} result has been determined offline. + * @return input stream, or {@code null} if none or if {@linkplain #probing} result has been determined externally. * * @see #createOutputStream() */ @@ -1407,7 +1437,7 @@ public class StorageConnector implements Serializable { * <p>This method is one of the {@link #OPENERS} methods and should be invoked at most once per * {@code StorageConnector} instance.</p> * - * @return input characters, or {@code null} if none or if {@linkplain #probing} result has been determined offline. + * @return input characters, or {@code null} if none or if {@linkplain #probing} result has been determined externally. */ private Reader createReader() throws IOException, DataStoreException { final InputStream input = getStorageAs(InputStream.class); @@ -1598,7 +1628,7 @@ public class StorageConnector implements Serializable { * <p>This method is one of the {@link #OPENERS} methods and should be invoked at most once per * {@code StorageConnector} instance.</p> * - * @return input stream, or {@code null} if none or if {@linkplain #probing} result has been determined offline. + * @return input stream, or {@code null} if none or if {@linkplain #probing} result has been determined externally. */ private ImageOutputStream createImageOutputStream() throws IOException, DataStoreException { final ImageOutputStream asDataOutput; @@ -1749,6 +1779,7 @@ public class StorageConnector implements Serializable { * @see #getStorageAs(Class) * @see DataStoreProvider#open(StorageConnector) */ + @SuppressWarnings("element-type-mismatch") public void closeAllExcept(final Object view) throws DataStoreException { if (views == null) { views = Map.of(); // For blocking future usage of this StorageConnector instance. diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/StorageConnectorTest.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/StorageConnectorTest.java index d9e9cf0013..6ac3d527e5 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/StorageConnectorTest.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/StorageConnectorTest.java @@ -219,6 +219,22 @@ public final class StorageConnectorTest extends TestCase { public void testGetAsImageInputStream() throws DataStoreException, IOException { final StorageConnector connector = create(false); final ImageInputStream in = connector.getStorageAs(ImageInputStream.class); + assertSame(connector.getStorageAs(ChannelImageInputStream.class), in); + assertSame(connector.getStorageAs(DataInput.class), in); + connector.closeAllExcept(null); + } + + /** + * Tests the {@link StorageConnector#getStorageAs(Class)} method for the {@link ChannelImageInputStream} type. + * + * @throws DataStoreException if an error occurred while using the storage connector. + * @throws IOException if an error occurred while reading the test file. + */ + @Test + public void testGetAsChannelImageInputStream() throws DataStoreException, IOException { + final StorageConnector connector = create(false); + final ChannelImageInputStream in = connector.getStorageAs(ChannelImageInputStream.class); + assertSame(connector.getStorageAs(ImageInputStream.class), in); assertSame(connector.getStorageAs(DataInput.class), in); connector.closeAllExcept(null); }