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 255a5b2bd73bcf4873d78a677eed30140f843e6d Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Sun Sep 17 14:51:39 2023 +0200 `ChannelDataInput` implements `DataInput` for allowing `instanceof` checks against a public interface. --- .../org/apache/sis/io/stream/ChannelDataInput.java | 125 +++++++++++++++++++-- .../sis/io/stream/ChannelImageInputStream.java | 70 +----------- .../apache/sis/io/stream/InputStreamAdapter.java | 58 +++++++++- .../org/apache/sis/storage/StorageConnector.java | 99 ++++++++-------- .../apache/sis/storage/StorageConnectorTest.java | 10 +- 5 files changed, 227 insertions(+), 135 deletions(-) diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/ChannelDataInput.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/ChannelDataInput.java index 5f0c4c5c9e..a7aa272888 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/ChannelDataInput.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/ChannelDataInput.java @@ -16,10 +16,13 @@ */ package org.apache.sis.io.stream; +import java.io.DataInput; +import java.io.DataInputStream; import java.io.IOException; import java.io.EOFException; import java.nio.Buffer; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.CharBuffer; import java.nio.ShortBuffer; import java.nio.IntBuffer; @@ -51,17 +54,14 @@ import static org.apache.sis.util.ArgumentChecks.ensureBetween; * <p>Since this class is only a helper tool, it does not "own" the channel and consequently does not provide * {@code close()} method. It is users responsibility to close the channel after usage.</p> * - * <h2>Relationship with {@code DataInput}</h2> - * This class API is compatibly with the {@link java.io.DataInput} interface, so subclasses can implement that - * interface if they wish. This class does not implement {@code DataInput} itself because it is not needed for - * SIS purposes, and because {@code DataInput} has undesirable methods ({@code readLine()} and {@code readUTF()}). - * However, the {@link ChannelImageInputStream} class implements the {@code DataInput} interface, together with - * the {@link javax.imageio.stream.ImageInputStream} one, mostly for situations when inter-operability with - * {@link javax.imageio} is needed. + * <h2>Relationship with {@code ChannelImageInputStream}</h2> + * This class API is compatible with the {@link javax.imageio.stream.ImageInputStream} interface, so subclasses + * can implement that interface if they wish. This is done by {@link ChannelImageInputStream} for situations + * when inter-operability with {@link javax.imageio} is needed. * * @author Martin Desruisseaux (Geomatys) */ -public class ChannelDataInput extends ChannelData { +public class ChannelDataInput extends ChannelData implements DataInput { /** * Minimum number of bytes to skip in the {@code seek(long)} operation. * If there is less bytes to skip, then it is not worth to do a seek @@ -173,7 +173,7 @@ public class ChannelDataInput extends ChannelData { /** * Returns {@code true} if the buffer or the channel has at least one byte remaining. - * If the {@linkplain #buffer buffer} has no remaining bytes, then this method will attempts + * If the {@linkplain #buffer buffer} has no remaining bytes, then this method will attempt * to read at least one byte from the {@linkplain #channel}. If no bytes can be read because * the channel has reached the end of stream, then this method returns {@code false}. * @@ -244,10 +244,10 @@ public class ChannelDataInput extends ChannelData { } /** - * Pushes back the last processed byte. This is used when a call to {@code readBit()} did not - * used every bits in a byte, or when {@code readLine()} checked for the Windows-style of EOL. + * Pushes back the last processed byte. This is used when a call to {@link #readBits(int)} did not + * used every bits in a byte, or when {@link #readLine()} checked for the Windows-style of EOL. */ - final void pushBack() { + private void pushBack() { buffer.position(buffer.position() - 1); } @@ -257,6 +257,8 @@ public class ChannelDataInput extends ChannelData { * * @return the value of the next bit from the stream. * @throws IOException if an error occurred while reading (including EOF). + * + * @see #readBoolean() */ public final int readBit() throws IOException { ensureBufferContains(Byte.BYTES); @@ -297,6 +299,26 @@ public class ChannelDataInput extends ChannelData { return value; } + /** + * Reads a byte from the stream and returns {@code true} if it is nonzero, {@code false} otherwise. + * The implementation is as below: + * + * {@snippet lang="java" : + * return readByte() != 0; + * } + * + * For reading a single bit, use {@link #readBit()} instead. + * + * @return the value of the next boolean from the stream. + * @throws IOException if an error (including EOF) occurred while reading the stream. + * + * @see #readBit() + */ + @Override + public final boolean readBoolean() throws IOException { + return readByte() != 0; + } + /** * Reads the next byte value (8 bits) from the stream. This method ensures that there is at * least 1 byte remaining in the buffer, reading new bytes from the channel if necessary, @@ -305,6 +327,7 @@ public class ChannelDataInput extends ChannelData { * @return the value of the next byte from the stream. * @throws IOException if an error (including EOF) occurred while reading the stream. */ + @Override public final byte readByte() throws IOException { ensureBufferContains(Byte.BYTES); return buffer.get(); @@ -321,6 +344,7 @@ public class ChannelDataInput extends ChannelData { * @return the value of the next unsigned byte from the stream. * @throws IOException if an error (including EOF) occurred while reading the stream. */ + @Override public final int readUnsignedByte() throws IOException { return Byte.toUnsignedInt(readByte()); } @@ -333,6 +357,7 @@ public class ChannelDataInput extends ChannelData { * @return the value of the next short from the stream. * @throws IOException if an error (including EOF) occurred while reading the stream. */ + @Override public final short readShort() throws IOException { ensureBufferContains(Short.BYTES); return buffer.getShort(); @@ -349,6 +374,7 @@ public class ChannelDataInput extends ChannelData { * @return the value of the next unsigned short from the stream. * @throws IOException if an error (including EOF) occurred while reading the stream. */ + @Override public final int readUnsignedShort() throws IOException { return Short.toUnsignedInt(readShort()); } @@ -361,6 +387,7 @@ public class ChannelDataInput extends ChannelData { * @return the value of the next character from the stream. * @throws IOException if an error (including EOF) occurred while reading the stream. */ + @Override public final char readChar() throws IOException { ensureBufferContains(Character.BYTES); return buffer.getChar(); @@ -374,6 +401,7 @@ public class ChannelDataInput extends ChannelData { * @return the value of the next integer from the stream. * @throws IOException if an error (including EOF) occurred while reading the stream. */ + @Override public final int readInt() throws IOException { ensureBufferContains(Integer.BYTES); return buffer.getInt(); @@ -402,6 +430,7 @@ public class ChannelDataInput extends ChannelData { * @return the value of the next integer from the stream. * @throws IOException if an error (including EOF) occurred while reading the stream. */ + @Override public final long readLong() throws IOException { ensureBufferContains(Long.BYTES); return buffer.getLong(); @@ -415,6 +444,7 @@ public class ChannelDataInput extends ChannelData { * @return the value of the next float from the stream. * @throws IOException if an error (including EOF) occurred while reading the stream. */ + @Override public final float readFloat() throws IOException { ensureBufferContains(Float.BYTES); return buffer.getFloat(); @@ -428,6 +458,7 @@ public class ChannelDataInput extends ChannelData { * @return the value of the next double from the stream. * @throws IOException if an error (including EOF) occurred while reading the stream. */ + @Override public final double readDouble() throws IOException { ensureBufferContains(Double.BYTES); return buffer.getDouble(); @@ -542,6 +573,7 @@ public class ChannelDataInput extends ChannelData { * @param dest An array of bytes to be written to. * @throws IOException if an error (including EOF) occurred while reading the stream. */ + @Override public final void readFully(final byte[] dest) throws IOException { readFully(dest, 0, dest.length); } @@ -555,6 +587,7 @@ public class ChannelDataInput extends ChannelData { * @param length the number of bytes to read. * @throws IOException if an error (including EOF) occurred while reading the stream. */ + @Override public final void readFully(final byte[] dest, int offset, int length) throws IOException { while (length != 0) { ensureNonEmpty(); @@ -896,6 +929,74 @@ public class ChannelDataInput extends ChannelData { return new String(array, position, length, encoding); } + /** + * Reads in a string that has been encoded using a UTF-8 string. + * + * @return the string reads from the stream. + * @throws IOException if an error (including EOF) occurred while reading the stream. + */ + @Override + public final String readUTF() throws IOException { + final ByteOrder oldOrder = buffer.order(); + buffer.order(ByteOrder.BIG_ENDIAN); + try { + return DataInputStream.readUTF(this); + } finally { + buffer.order(oldOrder); + } + } + + /** + * Reads new bytes until the next EOL. This method can read only US-ASCII strings. + * This method is provided for compliance with the {@link DataInput} interface, + * but is generally not recommended. + * + * @return the next line, or {@code null} if the EOF has been reached. + * @throws IOException if an error occurred while reading. + */ + @Override + public final String readLine() throws IOException { + if (!hasRemaining()) { + return null; + } + int c = Byte.toUnsignedInt(buffer.get()); + StringBuilder line = new StringBuilder(); + line.append((char) c); +loop: while (hasRemaining()) { + c = Byte.toUnsignedInt(buffer.get()); + switch (c) { + case '\n': break loop; + case '\r': { + if (hasRemaining() && buffer.get() != '\n') { + pushBack(); + } + break loop; + } + } + line.append((char) c); + } + return line.toString(); + } + + /** + * Tries to skip over <var>n</var> bytes of data from the input stream. + * This method may skip over some smaller number of bytes, possibly zero. + * A negative value move backward in the input stream. + * + * @param n maximal number of bytes to skip. Can be negative. + * @return number of bytes actually skipped. + * @throws IOException if an error occurred while reading. + */ + @Override + public int skipBytes(int n) throws IOException { + if (!hasRemaining()) { + return 0; + } + n = Math.min(n, buffer.remaining()); + buffer.position(buffer.position() + n); + return n; + } + /** * Moves to the given position in the stream. The given position is relative to * the position that the stream had at {@code ChannelDataInput} construction time. diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/ChannelImageInputStream.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/ChannelImageInputStream.java index e39b7cf8ae..04eeaead32 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/ChannelImageInputStream.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/ChannelImageInputStream.java @@ -16,7 +16,6 @@ */ package org.apache.sis.io.stream; -import java.io.DataInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -110,73 +109,6 @@ public class ChannelImageInputStream extends ChannelDataInput implements ImageIn return buffer.order(); } - /** - * Reads a byte from the stream and returns a {@code true} if it is nonzero, {@code false} otherwise. - * The implementation is as below: - * - * {@snippet lang="java" : - * return readByte() != 0; - * } - * - * @return the value of the next boolean from the stream. - * @throws IOException if an error (including EOF) occurred while reading the stream. - */ - @Override - public final boolean readBoolean() throws IOException { - return readByte() != 0; - } - - /** - * Reads in a string that has been encoded using a UTF-8 string. - * - * @return the string reads from the stream. - * @throws IOException if an error (including EOF) occurred while reading the stream. - */ - @Override - public final String readUTF() throws IOException { - final ByteOrder oldOrder = buffer.order(); - buffer.order(ByteOrder.BIG_ENDIAN); - try { - return DataInputStream.readUTF(this); - } finally { - buffer.order(oldOrder); - } - } - - /** - * Reads the new bytes until the next EOL. This method can read only US-ASCII strings. - * This method is provided for compliance with the {@link java.io.DataInput} interface, - * but is generally not recommended. - * - * @return the next line, or {@code null} if the EOF has been reached. - * @throws IOException if an error occurred while reading. - */ - @Override - public final String readLine() throws IOException { - int c = read(); - if (c < 0) { - return null; - } - StringBuilder line = new StringBuilder(); - line.append((char) c); -loop: while ((c = read()) >= 0) { - switch (c) { - case '\r': { - c = read(); - if (c >= 0 && c != '\n') { - pushBack(); - } - break loop; - } - case '\n': { - break loop; - } - } - line.append((char) c); - } - return line.toString(); - } - /** * Returns the next byte from the stream as an unsigned integer between 0 and 255, * or -1 if we reached the end of stream. @@ -259,7 +191,7 @@ loop: while ((c = read()) >= 0) { * But experience shows that various {@code ImageReader} implementations outside Apache SIS * expect that we skip exactly the specified amount of bytes and ignore the returned value. * - * @param n maximal number of bytes to skip. Can be negative. + * @param n number of bytes to skip. Can be negative. * @return number of bytes actually skipped. * @throws IOException if an error occurred while reading. */ diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/InputStreamAdapter.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/InputStreamAdapter.java index 92907a8c85..81f05db4b8 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/InputStreamAdapter.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/InputStreamAdapter.java @@ -42,8 +42,8 @@ import org.apache.sis.storage.internal.Resources; public final class InputStreamAdapter extends InputStream implements Markable { /** * The underlying data input stream. In principle, public access to this field breaks encapsulation. - * But since {@code InputStreamAdapter} does not hold any state and just forwards every method calls - * to that {@code ImageInputStream}, using on object or the other does not make a difference. + * But since {@code InputStreamAdapter} forwards most method calls to that {@code ImageInputStream}, + * using an object or the other does not make a difference except for marks and close operations. */ public final ImageInputStream input; @@ -119,6 +119,60 @@ public final class InputStreamAdapter extends InputStream implements Markable { return input.read(b, off, len); } + /** + * Reads up to a specified number of bytes from the input stream. + * This method may read less bytes if the end-of-stream is reached. + * + * @param count number of bytes to read. + * @return the bytes read. + * @throws IOException if an I/O error occurs. + */ + @Override + public byte[] readNBytes(int count) throws IOException { + final long length = input.length(); + if (length < 0) { + return super.readNBytes(count); + } + count = (int) Math.min(count, Math.subtractExact(length, input.getStreamPosition())); + final byte[] array = new byte[count]; + input.readFully(array); + return array; + } + + /** + * Reads up to a specified number of bytes from the input stream. + * This method may read less bytes if the end-of-stream is reached. + * + * @param array where to store the bytes. + * @param offset index if the first element where to store bytes. + * @param count number of bytes to read. + * @return number of bytes actually read. + * @throws IOException if an I/O error occurs. + */ + @Override + public int readNBytes(final byte[] array, final int offset, int count) throws IOException { + final long length = input.length(); + if (length < 0) { + return super.readNBytes(array, offset, count); + } + count = (int) Math.min(count, Math.subtractExact(length, input.getStreamPosition())); + input.readFully(array, offset, count); + return count; + } + + /** + * Skips the specified number of bytes. If the final position is past the end of file, + * an {@link java.io.EOFException} will be thrown either by this method or at the next + * read operation. + * + * @param count number of bytes to skip. + * @throws IOException if an I/O error occurs. + */ +// @Override // Pending JDK12. + public void skipNBytes(final long count) throws IOException { + input.seek(Math.addExact(input.getStreamPosition(), count)); + } + /** * Skips over and discards {@code n} bytes of data from this input stream. * 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 86ee0df6bf..0be3ca9ad4 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 @@ -213,7 +213,7 @@ public class StorageConnector implements Serializable { add(OutputStream.class, StorageConnector::createOutputStream); add(Reader.class, StorageConnector::createReader); add(Connection.class, StorageConnector::createConnection); - add(ChannelDataInput.class, (s) -> s.createChannelDataInput(false)); // Undocumented case (SIS internal) + 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. /* @@ -1017,13 +1017,12 @@ 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. * - * @param asImageInputStream whether the {@code ChannelDataInput} needs to be {@link ChannelImageInputStream} subclass. * @return input channel, or {@code null} if none or if {@linkplain #probing} result has been determined offline. * @throws IOException if an error occurred while opening a channel for the input. * * @see #createChannelDataOutput() */ - private ChannelDataInput createChannelDataInput(final boolean asImageInputStream) throws IOException, DataStoreException { + private ChannelDataInput createChannelDataInput() throws IOException, DataStoreException { /* * Before to try to wrap an InputStream, mark its position so we can rewind if the user asks for * the InputStream directly. We need to reset because ChannelDataInput may have read some bytes. @@ -1065,12 +1064,7 @@ public class StorageConnector implements Serializable { final ReadableByteChannel channel = factory.readable(name, null); addView(ReadableByteChannel.class, channel, null, factory.isCoupled() ? CASCADE_ON_RESET : 0); final ByteBuffer buffer = getChannelBuffer(factory); - final ChannelDataInput asDataInput; - if (asImageInputStream) { - asDataInput = new ChannelImageInputStream(name, channel, buffer, false); - } else { - asDataInput = new ChannelDataInput(name, channel, buffer, false); - } + final ChannelDataInput asDataInput = new ChannelDataInput(name, channel, buffer, false); addView(ChannelDataInput.class, asDataInput, ReadableByteChannel.class, CASCADE_ON_RESET); /* * Following is an undocumented mechanism for allowing some Apache SIS implementations of DataStore @@ -1107,20 +1101,15 @@ public class StorageConnector implements Serializable { if (reset(c)) { in = (ChannelDataInput) c.view; } else { - in = createChannelDataInput(true); // May be null. + in = createChannelDataInput(); // May be null. This method should not have been invoked before. } final DataInput asDataInput; if (in != null) { - c = getView(ChannelDataInput.class); // May have been added by createChannelDataInput(…). - if (in instanceof DataInput) { - asDataInput = (DataInput) in; - } else { - asDataInput = new ChannelImageInputStream(in); // Upgrade existing instance. - c.view = asDataInput; - } - views.put(DataInput.class, c); // Share the same Coupled instance. + asDataInput = in; + c = getView(ChannelDataInput.class); // Refresh because may have been added by createChannelDataInput(). + views.put(DataInput.class, c); // Share the same `Coupled` instance. } else if (wasProbingAbsentFile()) { - return null; // Do not cache, for allowing file creation later. + return null; // Do not cache, for allowing file creation later. } else { reset(); try { @@ -1195,8 +1184,8 @@ public class StorageConnector implements Serializable { /* * If no ChannelDataInput has been created by the above code, get the input as an ImageInputStream and * read an arbitrary number of bytes. Read only a small amount of bytes because, at the contrary of the - * buffer created in `createChannelDataInput(boolean)`, the buffer created here is unlikely to be used - * for the reading process after the recognition of the file format. + * buffer created in `createChannelDataInput()`, the buffer created here is unlikely to be used for the + * reading process after the recognition of the file format. */ final ImageInputStream in = getStorageAs(ImageInputStream.class); if (in != null) { @@ -1271,31 +1260,46 @@ public class StorageConnector implements Serializable { } /** - * Creates an {@link ImageInputStream} from the {@link DataInput} if possible. This method simply - * casts {@code DataInput} if such cast is allowed. Since {@link #createDataInput()} instantiates - * {@link ChannelImageInputStream}, this cast is usually possible. + * 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. * * <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. */ - private ImageInputStream createImageInputStream() throws DataStoreException { - final Class<DataInput> source = DataInput.class; - final DataInput input = getStorageAs(source); + private ImageInputStream createImageInputStream() throws IOException, DataStoreException { + final Coupled c; + final ImageInputStream asDataInput; + DataInput input = getStorageAs(DataInput.class); if (input instanceof ImageInputStream) { - views.put(ImageInputStream.class, views.get(source)); // Share the same Coupled instance. - return (ImageInputStream) input; - } else if (!wasProbingAbsentFile()) { - /* - * We do not invoke `ImageIO.createImageInputStream(Object)` because we do not know - * how the stream will use the `storage` object. It may read in advance some bytes, - * which can invalidate the storage for use outside the `ImageInputStream`. Instead - * creating image input/output streams is left to caller's responsibility. - */ - addView(ImageInputStream.class, null); // Remember that there is no view. + asDataInput = (ImageInputStream) input; + c = views.get(DataInput.class); + } else { + input = getStorageAs(ChannelDataInput.class); + if (input != null) { + c = getView(ChannelDataInput.class); + if (input instanceof ImageInputStream) { + asDataInput = (ImageInputStream) input; + } else { + asDataInput = new ChannelImageInputStream((ChannelDataInput) input); + c.view = asDataInput; // Upgrade existing instance for all views. + } + } else { + if (!wasProbingAbsentFile()) { + /* + * We do not invoke `ImageIO.createImageInputStream(Object)` because we do not know + * how the stream will use the `storage` object. It may read in advance some bytes, + * which can invalidate the storage for use outside the `ImageInputStream`. Instead + * creating image input/output streams is left to caller's responsibility. + */ + addView(ImageInputStream.class, null); // Remember that there is no view. + } + return null; + } } - return null; + views.put(ImageInputStream.class, c); // Share the same `Coupled` instance. + return asDataInput; } /** @@ -1310,18 +1314,19 @@ public class StorageConnector implements Serializable { * @see #createOutputStream() */ private InputStream createInputStream() throws IOException, DataStoreException { - final Class<DataInput> source = DataInput.class; - final DataInput input = getStorageAs(source); - if (input instanceof InputStream) { - views.put(InputStream.class, views.get(source)); // Share the same Coupled instance. - return (InputStream) input; - } else if (input instanceof ImageInputStream) { + final Class<ImageInputStream> source = ImageInputStream.class; + final ImageInputStream input = getStorageAs(source); + if (input != null) { + if (input instanceof InputStream) { + views.put(InputStream.class, views.get(source)); // Share the same `Coupled` instance. + return (InputStream) input; + } /* * Wrap the ImageInputStream as an ordinary InputStream. We avoid setting CASCADE_ON_RESET (unless * reset() needs to propagate further than ImageInputStream) because changes in InputStreamAdapter * position are immediately reflected by corresponding changes in ImageInputStream position. */ - final InputStream in = new InputStreamAdapter((ImageInputStream) input); + final InputStream in = new InputStreamAdapter(input); addView(InputStream.class, in, source, (byte) (getView(source).cascade & CASCADE_ON_RESET)); return in; } else if (!wasProbingAbsentFile()) { @@ -1418,7 +1423,7 @@ public class StorageConnector implements Serializable { * @return output channel, or {@code null} if none. * @throws IOException if an error occurred while opening a channel for the output. * - * @see #createChannelDataInput(boolean) + * @see #createChannelDataInput() */ private ChannelDataOutput createChannelDataOutput() throws IOException, DataStoreException { /* @@ -1517,7 +1522,7 @@ public class StorageConnector implements Serializable { final Class<DataOutput> target = DataOutput.class; final DataOutput output = getStorageAs(target); if (output instanceof OutputStream) { - views.put(OutputStream.class, views.get(target)); // Share the same Coupled instance. + views.put(OutputStream.class, views.get(target)); // Share the same `Coupled` instance. return (OutputStream) output; } else { addView(OutputStream.class, null); // Remember that there is no view. 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 2f010e4a61..bed05efd43 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 @@ -201,13 +201,13 @@ public final class StorageConnectorTest extends TestCase { assertEquals(asStream, connector.getStorageAs(Path.class) == null); final DataInput input = connector.getStorageAs(DataInput.class); assertSame("Value shall be cached.", input, connector.getStorageAs(DataInput.class)); - assertInstanceOf("Needs the SIS implementation.", ChannelImageInputStream.class, input); + assertInstanceOf("Needs the SIS implementation.", ChannelDataInput.class, input); assertSame("Instance shall be shared.", input, connector.getStorageAs(ChannelDataInput.class)); /* * Reads a single integer for checking that the stream is at the right position, then close the stream. * Since the file is a compiled Java class, the integer that we read shall be the Java magic number. */ - final ReadableByteChannel channel = ((ChannelImageInputStream) input).channel; + final ReadableByteChannel channel = ((ChannelDataInput) input).channel; assertTrue("channel.isOpen()", channel.isOpen()); assertEquals("First 4 bytes", MAGIC_NUMBER, input.readInt()); connector.closeAllExcept(null); @@ -343,7 +343,7 @@ public final class StorageConnectorTest extends TestCase { /* * Get as an image input stream and ensure that the cached value has been replaced. */ - final DataInput stream = connector.getStorageAs(DataInput.class); + final ImageInputStream stream = connector.getStorageAs(ImageInputStream.class); assertInstanceOf("Needs the SIS implementation", ChannelImageInputStream.class, stream); assertNotSame("Expected a new instance.", input, stream); assertSame("Shall share the channel.", input.channel, ((ChannelDataInput) stream).channel); @@ -439,8 +439,8 @@ public final class StorageConnectorTest extends TestCase { @DependsOnMethod("testGetAsDataInputFromStream") public void testCloseAllExcept() throws DataStoreException, IOException { final StorageConnector connector = create(true); - final DataInput input = connector.getStorageAs(DataInput.class); - final ReadableByteChannel channel = ((ChannelImageInputStream) input).channel; + final ChannelDataInput input = connector.getStorageAs(ChannelDataInput.class); + final ReadableByteChannel channel = input.channel; assertTrue("channel.isOpen()", channel.isOpen()); connector.closeAllExcept(input); assertTrue("channel.isOpen()", channel.isOpen());