sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1489608 - in /sis/branches/JDK7/storage/sis-storage/src: main/java/org/apache/sis/internal/storage/ main/java/org/apache/sis/storage/ test/java/org/apache/sis/internal/storage/ test/java/org/apache/sis/storage/
Date Tue, 04 Jun 2013 21:05:22 GMT
Author: desruisseaux
Date: Tue Jun  4 21:05:01 2013
New Revision: 1489608

URL: http://svn.apache.org/r1489608
Log:
Added support for String (path) and ImageInputStream types for convenience,
and added more tests.

Modified:
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreConnection.java
    sis/branches/JDK7/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/IOUtilitiesTest.java
    sis/branches/JDK7/storage/sis-storage/src/test/java/org/apache/sis/storage/DataStoreConnectionTest.java

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java?rev=1489608&r1=1489607&r2=1489608&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java
[UTF-8] Tue Jun  4 21:05:01 2013
@@ -115,6 +115,18 @@ public class ChannelImageInputStream ext
     }
 
     /**
+     * Creates a new input source from the given {@code ChannelDataInput}.
+     * This constructor is invoked when we need to change the implementation class
+     * from {@code ChannelDataInput} to {@code ChannelImageInputStream}.
+     *
+     * @param  input The existing instance from which to takes the channel and buffer.
+     * @throws IOException If an error occurred while reading the channel.
+     */
+    public ChannelImageInputStream(final ChannelDataInput input) throws IOException {
+        super(input.filename, input.channel, input.buffer, true);
+    }
+
+    /**
      * Sets the desired byte order for future reads of data values from this stream.
      * The default value is {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
      */

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java?rev=1489608&r1=1489607&r2=1489608&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java
[UTF-8] Tue Jun  4 21:05:01 2013
@@ -125,6 +125,27 @@ public final class IOUtilities extends S
     }
 
     /**
+     * Returns a string representation of the given path, or {@code null} if none. The current
implementation
+     * recognizes only the {@link Path}, {@link File}, {@link URL}, {@link URI} or {@link
CharSequence} types.
+     *
+     * @param  path The path for which to return a string representation.
+     * @return The string representation, or {@code null} if none.
+     */
+    public static String toString(final Object path) {
+        // For the following types, the string that we want can be obtained only by toString(),
+        // or the class is final so we know that the toString(à behavior can not be changed.
+        if (path instanceof CharSequence || path instanceof Path || path instanceof URL ||
path instanceof URI) {
+            return path.toString();
+        }
+        // While toString() would work too on the default implementation, the following
+        // type is not final. So we are better to invoke the dedicated method.
+        if (path instanceof File) {
+            return ((File) path).getPath();
+        }
+        return null;
+    }
+
+    /**
      * Encodes the characters that are not legal for the {@link URI#URI(String)} constructor.
      * Note that in addition to unreserved characters ("{@code _-!.~'()*}"), the reserved
      * characters ("{@code ?/[]@}") and the punctuation characters ("{@code ,;:$&+=}")

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreConnection.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreConnection.java?rev=1489608&r1=1489607&r2=1489608&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreConnection.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreConnection.java
[UTF-8] Tue Jun  4 21:05:01 2013
@@ -34,6 +34,7 @@ import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.storage.IOUtilities;
+import org.apache.sis.internal.storage.ChannelDataInput;
 import org.apache.sis.internal.storage.ChannelImageInputStream;
 import org.apache.sis.setup.OptionKey;
 
@@ -77,7 +78,7 @@ public class DataStoreConnection impleme
      * The default size of the {@link ByteBuffer} to be created.
      * Users can override this value by providing a value for {@link OptionKey#BYTE_BUFFER}.
      */
-    private static final int DEFAULT_BUFFER_SIZE = 4096;
+    static final int DEFAULT_BUFFER_SIZE = 4096;
 
     /**
      * The input/output object given at construction time.
@@ -111,8 +112,11 @@ public class DataStoreConnection impleme
      *       stream. In particular, we invoke the {@link ImageIO#createImageInputStream(Object)}
factory method only in
      *       last resort because some SIS data stores will want to access the channel and
buffer directly.</li>
      *
+     *   <li>{@link ImageInputStream}:
+     *       Same as {@code DataInput} if it can be casted, or {@code null} otherwise.</li>
+     *
      *   <li>{@link Connection}:
-     *       The input/output object as a JDBC connection.</li>
+     *       The storage object as a JDBC connection.</li>
      * </ul>
      *
      * A non-existent entry means that the value has not yet been computed. A {@link Void#TYPE}
value means the value
@@ -235,6 +239,15 @@ public class DataStoreConnection impleme
      * The default implementation accepts the following types:
      *
      * <ul>
+     *   <li>{@link String}:
+     *     <ul>
+     *       <li>If the {@linkplain #getStorage() storage} object is an instance of
the {@link java.nio.file.Path},
+     *           {@link java.io.File}, {@link java.net.URL}, {@link java.net.URI} or {@link
CharSequence} types,
+     *           returns the string representation of their path.</li>
+     *
+     *       <li>Otherwise this method returns {@code null}.</li>
+     *     </ul>
+     *   </li>
      *   <li>{@link ByteBuffer}:
      *     <ul>
      *       <li>If the {@linkplain #getStorage() storage} object can be obtained as
described in bullet 2 of the
@@ -260,6 +273,13 @@ public class DataStoreConnection impleme
      *       <li>Otherwise this method returns {@code null}.</li>
      *     </ul>
      *   </li>
+     *   <li>{@link ImageInputStream}:
+     *     <ul>
+     *       <li>If the {@code DataInput} computed above can be casted to {@code null},
returns it.</li>
+     *
+     *       <li>Otherwise this method returns {@code null}.</li>
+     *     </ul>
+     *   </li>
      *   <li>{@link Connection}:
      *     <ul>
      *       <li>If the {@linkplain #getStorage() storage} object is already an instance
of {@link Connection},
@@ -302,13 +322,26 @@ public class DataStoreConnection impleme
         /*
          * Special case for DataInput and ByteBuffer, because those values are created together.
          * In addition, ImageInputStream creation assigns a value to the 'streamOrigin' field.
+         * The ChannelDataInput case is an undocumented (SIS internal) type for avoiding
the
+         * potential call to ImageIO.createImageInputStream(…) when we do not need it.
          */
-        if (type == DataInput.class || type == ByteBuffer.class) {
-            try {
+        boolean done = false;
+        try {
+            if (type == ByteBuffer.class) {
+                createByteBuffer();
+                done = true;
+            } else if (type == DataInput.class) {
                 createDataInput();
-            } catch (IOException e) {
-                throw new DataStoreException(Errors.format(Errors.Keys.CanNotOpen_1, getStorageName()),
e);
+                done = true;
+            } else if (type == ChannelDataInput.class) { // Undocumented case (SIS internal)
+                createChannelDataInput(false);
+                done = true;
             }
+        } catch (IOException e) {
+            throw new DataStoreException(Errors.format(Errors.Keys.CanNotOpen_1, getStorageName()),
e);
+        }
+        if (done) {
+            // Want to exit this method even if the value is null.
             return getView(type);
         }
         /*
@@ -328,6 +361,32 @@ public class DataStoreConnection impleme
     }
 
     /**
+     * Creates a view for the input as a {@link ChannelDataInput} if possible.
+     *
+     * @param  asImageInputStream If the {@code ChannelDataInput} needs to be {@link ChannelImageInputStream}
subclass.
+     * @throws IOException If an error occurred while opening a channel for the input.
+     */
+    private void createChannelDataInput(final boolean asImageInputStream) throws IOException
{
+        final ReadableByteChannel channel = IOUtilities.open(storage, getOption(OptionKey.URL_ENCODING));
+        ChannelDataInput asDataInput = null;
+        if (channel != null) {
+            ByteBuffer buffer = getOption(OptionKey.BYTE_BUFFER);
+            if (buffer == null) {
+                buffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
+                // TODO: we do not create direct buffer yet, but this is something
+                // we may want to consider in a future SIS version.
+            }
+            final String name = getStorageName();
+            if (asImageInputStream) {
+                asDataInput = new ChannelImageInputStream(name, channel, buffer, false);
+            } else {
+                asDataInput = new ChannelDataInput(name, channel, buffer, false);
+            }
+        }
+        addView(ChannelDataInput.class, asDataInput);
+    }
+
+    /**
      * Creates a view for the input as a {@link DataInput} if possible. This method performs
the choice
      * documented in the {@link #getStorageAs(Class)} method for the {@code DataInput} case.
Opening the
      * data input may imply creating a {@link ByteBuffer}, in which case the buffer will
be stored under
@@ -337,7 +396,6 @@ public class DataStoreConnection impleme
      */
     private void createDataInput() throws IOException {
         final DataInput asDataInput;
-        ByteBuffer asByteBuffer = null;
         if (storage instanceof DataInput) {
             asDataInput = (DataInput) storage;
         } else {
@@ -346,41 +404,54 @@ public class DataStoreConnection impleme
              * SIS data stores will want to access directly the channel and the buffer. We
will fallback
              * on the ImageIO.createImageInputStream(Object) method only in last resort.
              */
-            final ReadableByteChannel channel = IOUtilities.open(storage, getOption(OptionKey.URL_ENCODING));
-            if (channel != null) {
-                ByteBuffer buffer = getOption(OptionKey.BYTE_BUFFER);
-                if (buffer == null) {
-                    buffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
-                    // TODO: we do not create direct buffer yet, but this is something
-                    // we may want to consider in a future SIS version.
-                }
-                asDataInput = new ChannelImageInputStream(getStorageName(), channel, buffer,
false);
-                asByteBuffer = buffer.asReadOnlyBuffer();
-            } else {
+            if (!views.containsKey(ChannelDataInput.class)) {
+                createChannelDataInput(true);
+            }
+            final ChannelDataInput c = getView(ChannelDataInput.class);
+            if (c == null) {
                 asDataInput = ImageIO.createImageInputStream(storage);
+            } else if (c instanceof DataInput) {
+                asDataInput = (DataInput) c;
+            } else {
+                asDataInput = new ChannelImageInputStream(c);
+                if (views.put(ChannelDataInput.class, asDataInput) != c) {
+                    throw new ConcurrentModificationException();
+                }
             }
         }
-        /*
-         * If an ImageInputStream has been created without buffer, read an arbitrary amount
of bytes now
-         * so we can provide a ByteBuffer in case some user wants it. This may be a unnecessary
overhead
-         * since maybe no user will want to look at a ByteBuffer,  but this case is presumed
rare enough
-         * for not being worth a more complex "lazy instantiation" mechanism. We read only
a small amount
-         * of bytes because, at the contrary of the buffer created in the above block, the
buffer created
-         * here is unlikely to be used for the reading process after the recognition of the
file format.
-         */
-        if (asByteBuffer == null && asDataInput instanceof ImageInputStream) {
-            final ImageInputStream in = (ImageInputStream) asDataInput;
-            in.mark();
-            final byte[] buffer = new byte[256];
-            final int n = in.read(buffer);
-            in.reset();
-            if (n >= 1) {
-                asByteBuffer = ByteBuffer.wrap(ArraysExt.resize(buffer, n))
-                        .asReadOnlyBuffer().order(in.getByteOrder());
+        addView(DataInput.class, asDataInput);
+    }
+
+    /**
+     * If an {@link ImageInputStream} has been created without buffer, read an arbitrary
amount of bytes now so
+     * we can provide a {@link ByteBuffer} for users who want it. We read only a small amount
of bytes because,
+     * at the contrary of the buffer created in {@link #createChannelAndBuffer(boolean)},
the buffer created
+     * here is unlikely to be used for the reading process after the recognition of the file
format.
+     *
+     * @throws IOException If an error occurred while opening a stream for the input.
+     */
+    private void createByteBuffer() throws IOException, DataStoreException {
+        if (!views.containsKey(ChannelDataInput.class)) {
+            createChannelDataInput(false);
+        }
+        ByteBuffer asByteBuffer = null;
+        final ChannelDataInput c = getView(ChannelDataInput.class);
+        if (c != null) {
+            asByteBuffer = c.buffer.asReadOnlyBuffer();
+        } else {
+            final ImageInputStream in = getStorageAs(ImageInputStream.class);
+            if (in != null) {
+                in.mark();
+                final byte[] buffer = new byte[256];
+                final int n = in.read(buffer);
+                in.reset();
+                if (n >= 1) {
+                    asByteBuffer = ByteBuffer.wrap(ArraysExt.resize(buffer, n))
+                            .asReadOnlyBuffer().order(in.getByteOrder());
+                }
             }
         }
         addView(ByteBuffer.class, asByteBuffer);
-        addView(DataInput.class,  asDataInput);
     }
 
     /**
@@ -394,6 +465,9 @@ public class DataStoreConnection impleme
      * @throws Exception If an error occurred while opening a stream or database connection.
      */
     private Object createView(final Class<?> type) throws IllegalArgumentException,
Exception {
+        if (type == String.class) {
+            return IOUtilities.toString(storage);
+        }
         if (type == Connection.class) {
             if (storage instanceof Connection) {
                 return storage;
@@ -401,11 +475,15 @@ public class DataStoreConnection impleme
                 return ((DataSource) storage).getConnection();
             }
         }
+        if (type == ImageInputStream.class) {
+            final DataInput input = getStorageAs(DataInput.class);
+            return (input instanceof ImageInputStream) ? input : null;
+        }
         throw new IllegalArgumentException(Errors.format(Errors.Keys.UnknownType_1, type));
     }
 
     /**
-     * Adds the given view in the caches.
+     * Adds the given view in the cache.
      *
      * @param <T>   The compile-time type of the {@code type} argument.
      * @param type  The view type.
@@ -418,7 +496,7 @@ public class DataStoreConnection impleme
     }
 
     /**
-     * Returns the view for the given type from the caches.
+     * Returns the view for the given type from the cache.
      *
      * @param <T>   The compile-time type of the {@code type} argument.
      * @param type  The view type.
@@ -447,22 +525,25 @@ public class DataStoreConnection impleme
      * @see #getStorageAs(Class)
      */
     public void closeAllExcept(final Object view) throws DataStoreException {
-        boolean close = (view == null);
+        /*
+         * Need a set of objects to close without duplicated values. In particular, the value
for
+         * DataInput and ImageInputStream are often the same instance. We must avoid duplicated
+         * values because ImageInputStream.close() is not indempotent.
+         */
+        final Map<AutoCloseable,Object> toClose = new IdentityHashMap<>(4);
+        for (final Object value : views.values()) {
+            if (value instanceof AutoCloseable) {
+                toClose.put((AutoCloseable) value, null);
+            }
+        }
+        toClose.remove(view);
+        toClose.remove(storage);
         try {
-            for (final Object value : views.values()) {
-                if (value != view) {
-                    if (value instanceof AutoCloseable) {
-                        ((AutoCloseable) value).close();
-                        close = false;
-                    }
+            if (!toClose.isEmpty()) {
+                for (final AutoCloseable value : toClose.keySet()) {
+                    value.close();
                 }
-                /*
-                 * On JDK6, ImageInputStream does not extend Closeable and must
-                 * be checked explicitely. On JDK7, this is not needed anymore.
-                 * Likewise, Connection extends AutoCloseable only in JDK7.
-                 */
-            }
-            if (close && storage instanceof AutoCloseable) {
+            } else if (view == null && storage instanceof AutoCloseable) {
                 /*
                  * Close only if we didn't closed a view because closing an input stream
view
                  * automatically close the 'storage' if the former is a wrapper for the later.

Modified: sis/branches/JDK7/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/IOUtilitiesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/IOUtilitiesTest.java?rev=1489608&r1=1489607&r2=1489608&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/IOUtilitiesTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/IOUtilitiesTest.java
[UTF-8] Tue Jun  4 21:05:01 2013
@@ -75,6 +75,22 @@ public final strictfp class IOUtilitiesT
     }
 
     /**
+     * Tests {@link IOUtilities#toString(Object)}.
+     *
+     * @throws URISyntaxException Should never happen.
+     * @throws MalformedURLException Should never happen.
+     */
+    @Test
+    public void testToString() throws URISyntaxException, MalformedURLException {
+        // Do not test File because the result is platform-specific.
+        assertEquals("/Users/name/Map.png",      IOUtilities.toString(              "/Users/name/Map.png"));
+        assertEquals("file:/Users/name/Map.png", IOUtilities.toString(new URI ("file:/Users/name/Map.png")));
+        assertEquals("file:/Users/name/Map.png", IOUtilities.toString(new URL ("file:/Users/name/Map.png")));
+        assertNull(IOUtilities.toString(Boolean.FALSE));
+        assertNull(IOUtilities.toString(null));
+    }
+
+    /**
      * Tests {@link IOUtilities#encodeURI(String)}.
      */
     @Test

Modified: sis/branches/JDK7/storage/sis-storage/src/test/java/org/apache/sis/storage/DataStoreConnectionTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/test/java/org/apache/sis/storage/DataStoreConnectionTest.java?rev=1489608&r1=1489607&r2=1489608&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/test/java/org/apache/sis/storage/DataStoreConnectionTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/test/java/org/apache/sis/storage/DataStoreConnectionTest.java
[UTF-8] Tue Jun  4 21:05:01 2013
@@ -20,6 +20,9 @@ import java.io.DataInput;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.channels.ReadableByteChannel;
+import javax.imageio.ImageIO;
+import javax.imageio.stream.ImageInputStream;
+import org.apache.sis.internal.storage.ChannelDataInput;
 import org.apache.sis.internal.storage.ChannelImageInputStream;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
@@ -75,6 +78,18 @@ public final strictfp class DataStoreCon
     }
 
     /**
+     * Tests the {@link DataStoreConnection#getStorageAs(Class)} method for the {@link String}
type.
+     *
+     * @throws DataStoreException Should never happen.
+     * @throws IOException Should never happen.
+     */
+    @Test
+    public void testGetAsString() throws DataStoreException, IOException {
+        final DataStoreConnection c = create(false);
+        assertTrue(c.getStorageAs(String.class).endsWith("org/apache/sis/storage/DataStoreConnectionTest.class"));
+    }
+
+    /**
      * Tests the {@link DataStoreConnection#getStorageAs(Class)} method for the I/O types.
      * The initial storage object is a {@link java.net.URL}.
      *
@@ -82,8 +97,8 @@ public final strictfp class DataStoreCon
      * @throws IOException If an error occurred while reading the test file.
      */
     @Test
-    public void testOpenFromURL() throws DataStoreException, IOException {
-        testOpenAsDataInput(false);
+    public void testGetAsDataInputFromURL() throws DataStoreException, IOException {
+        testGetAsDataInput(false);
     }
 
     /**
@@ -94,23 +109,24 @@ public final strictfp class DataStoreCon
      * @throws IOException If an error occurred while reading the test file.
      */
     @Test
-    public void testOpenFromStream() throws DataStoreException, IOException {
-        testOpenAsDataInput(true);
+    public void testGetAsDataInputFromStream() throws DataStoreException, IOException {
+        testGetAsDataInput(true);
     }
 
     /**
-     * Implementation of {@link #testOpenFromURL()} and {@link #testOpenFromStream()}.
+     * Implementation of {@link #testGetAsDataInputFromURL()} and {@link #testGetAsDataInputFromStream()}.
      */
-    private void testOpenAsDataInput(final boolean asStream) throws DataStoreException, IOException
{
+    private void testGetAsDataInput(final boolean asStream) throws DataStoreException, IOException
{
         final DataStoreConnection connection = create(asStream);
         final DataInput input = connection.getStorageAs(DataInput.class);
         assertSame("Value shall be cached.", input, connection.getStorageAs(DataInput.class));
         assertInstanceOf("Needs the SIS implementation", ChannelImageInputStream.class, input);
-        final ReadableByteChannel channel = ((ChannelImageInputStream) input).channel;
+        assertSame("Instance shall be shared.", input, connection.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;
         assertTrue("channel.isOpen()", channel.isOpen());
         assertEquals(MAGIC_NUMBER, input.readInt());
         connection.closeAllExcept(null);
@@ -118,17 +134,86 @@ public final strictfp class DataStoreCon
     }
 
     /**
+     * Tests the {@link DataStoreConnection#getStorageAs(Class)} method for the {@link ImageInputStream}
type.
+     * This is basically a synonymous of {@code getStorageAs(DataInput.class)}.
+     *
+     * @throws DataStoreException Should never happen.
+     * @throws IOException If an error occurred while reading the test file.
+     */
+    @Test
+    public void testGetAsImageInputStream() throws DataStoreException, IOException {
+        final DataStoreConnection connection = create(false);
+        final ImageInputStream in = connection.getStorageAs(ImageInputStream.class);
+        assertSame(connection.getStorageAs(DataInput.class), in);
+        connection.closeAllExcept(null);
+    }
+
+    /**
+     * Tests the {@link DataStoreConnection#getStorageAs(Class)} method for the {@link ChannelDataInput}
type.
+     * The initial value should not be an instance of {@link ChannelImageInputStream} in
order to avoid initializing
+     * the Image I/O classes. However after a call to {@getStorageAt(ChannelImageInputStream.class)},
the type should
+     * have been promoted.
+     *
+     * @throws DataStoreException Should never happen.
+     * @throws IOException If an error occurred while reading the test file.
+     */
+    @Test
+    public void testGetAsChannelDataInput() throws DataStoreException, IOException {
+        final DataStoreConnection connection = create(true);
+        final ChannelDataInput input = connection.getStorageAs(ChannelDataInput.class);
+        assertFalse(input instanceof ChannelImageInputStream);
+        assertEquals(MAGIC_NUMBER, input.buffer.getInt());
+        /*
+         * Get as an image input stream and ensure that the cached value has been replaced.
+         */
+        final DataInput stream = connection.getStorageAs(DataInput.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);
+        assertSame("Shall share the buffer.",  input.buffer,  ((ChannelDataInput) stream).buffer);
+        assertSame("Cached valud shall have been replaced.", stream, connection.getStorageAs(ChannelDataInput.class));
+        connection.closeAllExcept(null);
+    }
+
+    /**
      * Tests the {@link DataStoreConnection#getStorageAs(Class)} method for the {@link ByteBuffer}
type.
-     * This method uses the same test file than {@link #testOpenFromURL()}.
+     * This method uses the same test file than {@link #testGetAsDataInputFromURL()}.
      *
      * @throws DataStoreException Should never happen.
      * @throws IOException If an error occurred while reading the test file.
      */
     @Test
-    @DependsOnMethod("testOpenFromURL")
-    public void testOpenAsByteBuffer() throws DataStoreException, IOException {
+    @DependsOnMethod("testGetAsDataInputFromURL")
+    public void testGetAsByteBuffer() throws DataStoreException, IOException {
         final DataStoreConnection connection = create(false);
         final ByteBuffer buffer = connection.getStorageAs(ByteBuffer.class);
+        assertNotNull("getStorageAs(ByteBuffer.class)", buffer);
+        assertEquals(DataStoreConnection.DEFAULT_BUFFER_SIZE, buffer.capacity());
+        assertEquals(MAGIC_NUMBER, buffer.getInt());
+        connection.closeAllExcept(null);
+    }
+
+    /**
+     * Tests the {@link DataStoreConnection#getStorageAs(Class)} method for the {@link ByteBuffer}
type when
+     * the buffer is only temporary. The difference between this test and {@link testGetAsByteBuffer()}
is
+     * that the buffer created in this test will not be used for the "real" reading process
in the data store.
+     * Consequently, it should be a smaller, only temporary, buffer.
+     *
+     * @throws DataStoreException Should never happen.
+     * @throws IOException If an error occurred while reading the test file.
+     */
+    @Test
+    @DependsOnMethod("testGetAsDataInputFromStream")
+    public void testGetAsTemporaryByteBuffer() throws DataStoreException, IOException {
+        DataStoreConnection connection = create(true);
+        final DataInput in = ImageIO.createImageInputStream(connection.getStorage());
+        assertNotNull("ImageIO.createImageInputStream(InputStream)", in); // Sanity check.
+        connection = new DataStoreConnection(in);
+        assertSame(in, connection.getStorageAs(DataInput.class));
+
+        final ByteBuffer buffer = connection.getStorageAs(ByteBuffer.class);
+        assertNotNull("getStorageAs(ByteBuffer.class)", buffer);
+        assertTrue(buffer.capacity() < DataStoreConnection.DEFAULT_BUFFER_SIZE);
         assertEquals(MAGIC_NUMBER, buffer.getInt());
         connection.closeAllExcept(null);
     }
@@ -140,7 +225,7 @@ public final strictfp class DataStoreCon
      * @throws IOException If an error occurred while reading the test file.
      */
     @Test
-    @DependsOnMethod("testOpenFromStream")
+    @DependsOnMethod("testGetAsDataInputFromStream")
     public void testCloseAllExcept() throws DataStoreException, IOException {
         final DataStoreConnection connection = create(true);
         final DataInput input = connection.getStorageAs(DataInput.class);



Mime
View raw message