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 696dfafa870b352593dba3dd6e5449294e799cd5
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Aug 17 18:02:41 2022 +0200

    Allow `ChannelImageInputStream` to wrap an array of `byte[]` containing all 
data.
---
 .../sis/internal/storage/io/ChannelData.java       | 25 ++++++-
 .../sis/internal/storage/io/ChannelDataInput.java  | 15 ++++-
 .../storage/io/ChannelImageInputStream.java        | 14 +++-
 .../sis/internal/storage/io/NullChannel.java       | 77 ++++++++++++++++++++++
 .../sis/internal/storage/io/package-info.java      |  2 +-
 .../org/apache/sis/storage/StorageConnector.java   | 11 +++-
 6 files changed, 137 insertions(+), 7 deletions(-)

diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelData.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelData.java
index 19b2c50287..e45ca2fcdf 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelData.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelData.java
@@ -32,7 +32,7 @@ import static 
org.apache.sis.util.ArgumentChecks.ensureBetween;
  * querying or modifying the stream position. This class does not define any 
read or write operations.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -125,6 +125,21 @@ public abstract class ChannelData implements Markable {
         this.channelOffset = (channel instanceof SeekableByteChannel) ? 
((SeekableByteChannel) channel).position() : 0;
     }
 
+    /**
+     * Creates a new instance for a buffer filled with the bytes to use.
+     * This constructor uses an independent, read-only view of the given 
buffer.
+     * No reference to the given buffer will be retained.
+     *
+     * @param  filename  a short identifier (typically a filename without 
path) used for formatting error message.
+     * @param  data      the buffer filled with all bytes to read.
+     */
+    ChannelData(final String filename, final ByteBuffer data) {
+        this.filename = filename;
+        buffer = data.asReadOnlyBuffer();
+        buffer.order(data.order());
+        channelOffset = 0;
+    }
+
     /**
      * Implementation of {@link ChannelDataInput#readBit()} provided here for 
performance reasons.
      * It is caller responsibility to ensure that the {@link #buffer} contains 
at least one byte.
@@ -245,9 +260,10 @@ public abstract class ChannelData implements Markable {
     /**
      * Discards the initial portion of the stream prior to the indicated 
position.
      * Attempting to {@linkplain #seek(long) seek} to an offset within the 
flushed
-     * portion of the stream will result in an {@link 
IndexOutOfBoundsException}.
+     * portion of the stream may result in an {@link 
IndexOutOfBoundsException}.
      *
-     * <p>This method moves the data starting at the given position to the 
beginning of the {@link #buffer},
+     * <p>If the {@link #buffer} is read-only, then this method does nothing. 
Otherwise
+     * this method moves the data starting at the given position to the 
beginning of the {@link #buffer},
      * thus making more room for new data before the data at the given 
position is discarded.</p>
      *
      * @param  position  the length of the stream prefix that may be flushed.
@@ -259,6 +275,9 @@ public abstract class ChannelData implements Markable {
             throw new 
IndexOutOfBoundsException(Errors.format(Errors.Keys.ValueOutOfRange_4,
                     "position", bufferOffset, currentPosition, position));
         }
+        if (buffer.isReadOnly()) {
+            return;
+        }
         final int n = (int) Math.max(position - bufferOffset, 0);
         final int p = buffer.position() - n;
         final int r = buffer.limit() - n;
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java
index 335667359b..389716e584 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java
@@ -60,7 +60,7 @@ import static 
org.apache.sis.util.ArgumentChecks.ensureBetween;
  * {@link javax.imageio} is needed.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -106,6 +106,19 @@ public class ChannelDataInput extends ChannelData {
         }
     }
 
+    /**
+     * Creates a new instance for a buffer filled with the bytes to use.
+     * This constructor uses an independent, read-only view of the given 
buffer.
+     * No reference to the given buffer will be retained.
+     *
+     * @param  filename  a short identifier (typically a filename without 
path) used for formatting error message.
+     * @param  data      the buffer filled with all bytes to read.
+     */
+    public ChannelDataInput(final String filename, final ByteBuffer data) {
+        super(filename, data);
+        channel = new NullChannel();
+    }
+
     /**
      * Returns the length of the stream (in bytes), or -1 if unknown.
      * The length is relative to the channel position at {@linkplain 
#ChannelDataInput construction time}.
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelImageInputStream.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelImageInputStream.java
index 9a8a3c0186..3b875bfe29 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelImageInputStream.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelImageInputStream.java
@@ -42,7 +42,7 @@ import javax.imageio.stream.ImageInputStream;
  * <p>This class is used when compatibility with {@link 
javax.imageio.ImageReader} is needed.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
  *
  * @see javax.imageio.stream.FileImageInputStream
  * @see javax.imageio.ImageIO#createImageInputStream(Object)
@@ -68,6 +68,18 @@ public class ChannelImageInputStream extends 
ChannelDataInput implements ImageIn
         super(filename, channel, buffer, filled);
     }
 
+    /**
+     * Creates a new instance for a buffer filled with the bytes to use.
+     * This constructor uses an independent, read-only view of the given 
buffer.
+     * No reference to the given buffer will be retained.
+     *
+     * @param  filename  a short identifier (typically a filename without 
path) used for formatting error message.
+     * @param  data      the buffer filled with all bytes to read.
+     */
+    public ChannelImageInputStream(final String filename, final ByteBuffer 
data) {
+        super(filename, data);
+    }
+
     /**
      * Creates a new input stream from the given {@code ChannelDataInput}.
      * This constructor is invoked when we need to change the implementation 
class
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/NullChannel.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/NullChannel.java
new file mode 100644
index 0000000000..2486e11828
--- /dev/null
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/NullChannel.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.storage.io;
+
+import java.util.Objects;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ClosedChannelException;
+
+
+/**
+ * A channel which read no values. This class behaves as if the channel 
already reached the end of file.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.3
+ * @since   1.3
+ * @module
+ */
+final class NullChannel implements ReadableByteChannel {
+    /**
+     * Whether this channel has been closed.
+     */
+    private volatile boolean closed;
+
+    /**
+     * Creates an initially open channel.
+     */
+    NullChannel() {
+    }
+
+    /**
+     * Pretends to read a sequence of bytes and indicates that the channel 
reached the end of file.
+     * Read-only buffers are accepted (this is required for {@link 
ChannelImageInputStream}).
+     *
+     * @param  dst  ignored except for non-null check.
+     * @return always -1.
+     * @throws ClosedChannelException if this channel has been closed.
+     */
+    @Override
+    public int read(ByteBuffer dst) throws ClosedChannelException {
+        Objects.requireNonNull(dst);
+        if (closed) {
+            throw new ClosedChannelException();
+        }
+        return -1;
+    }
+
+    /**
+     * Returns whether this channel is still open.
+     */
+    @Override
+    public boolean isOpen() {
+        return !closed;
+    }
+
+    /**
+     * Closes this channel. If this channel is already closed, then this 
method does nothing.
+     */
+    @Override
+    public void close() {
+        closed = true;
+    }
+}
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/package-info.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/package-info.java
index e2932d1265..de0e699a69 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/package-info.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/package-info.java
@@ -24,7 +24,7 @@
  * may change in incompatible ways in any future version without notice.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
  * @since   0.3
  * @module
  */
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
index 2f2fab45f3..5560158acd 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
@@ -99,7 +99,7 @@ import org.apache.sis.setup.OptionKey;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Alexis Manin (Geomatys)
- * @version 1.2
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -711,6 +711,10 @@ public class StorageConnector implements Serializable {
      *           (including the {@link ImageInputStream} and {@link 
javax.imageio.stream.ImageOutputStream} types),
      *           then it is returned unchanged.</li>
      *
+     *       <li>Otherwise if the input is an instance of {@link ByteBuffer}, 
then an {@link ImageInputStream}
+     *           backed by a read-only view of that buffer is created when 
first needed and returned.
+     *           The properties (position, mark, limit) of the original buffer 
are unmodified.</li>
+     *
      *       <li>Otherwise if the input is an instance of {@link 
java.nio.file.Path}, {@link java.io.File},
      *           {@link java.net.URI}, {@link java.net.URL}, {@link 
CharSequence}, {@link InputStream} or
      *           {@link java.nio.channels.ReadableByteChannel}, then an {@link 
ImageInputStream} backed by a
@@ -953,6 +957,11 @@ public class StorageConnector implements Serializable {
         if (storage instanceof InputStream) {
             ((InputStream) storage).mark(DEFAULT_BUFFER_SIZE);
         }
+        if (storage instanceof ByteBuffer) {
+            final ChannelDataInput asDataInput = new 
ChannelImageInputStream(getStorageName(), (ByteBuffer) storage);
+            addView(ChannelDataInput.class, asDataInput);
+            return asDataInput;
+        }
         /*
          * Following method call recognizes ReadableByteChannel, InputStream 
(with optimization for FileInputStream),
          * URL, URI, File, Path or other types that may be added in future 
Apache SIS versions.

Reply via email to