sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1509300 - in /sis/branches/JDK7: core/sis-utility/src/main/java/org/apache/sis/setup/ storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/ storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/ storage/sis-storage/src/m...
Date Thu, 01 Aug 2013 15:33:07 GMT
Author: desruisseaux
Date: Thu Aug  1 15:33:07 2013
New Revision: 1509300

URL: http://svn.apache.org/r1509300
Log:
Revisit the strategy about DataStore OpenOptions: move them as options given to StorageConnector,
because we need
to know them when the ByteChannel is created (having the options in DataStoreProvider.canOpen(...)
was too late).
As a side effect, the OpenOption are not anymore directly in the method signature, which will
make the port to
the JDK6 branch a little bit easier.

Added:
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java
      - copied, changed from r1509040, sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/OpenOption.java
Removed:
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/OpenOption.java
Modified:
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/setup/OptionKey.java
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
    sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.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/DataStoreProvider.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/setup/OptionKey.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/setup/OptionKey.java?rev=1509300&r1=1509299&r2=1509300&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/setup/OptionKey.java [UTF-8]
(original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/setup/OptionKey.java [UTF-8]
Thu Aug  1 15:33:07 2013
@@ -24,6 +24,10 @@ import java.io.ObjectStreamException;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.logging.Logging;
 
+// Related to JDK7
+import java.nio.file.OpenOption;
+import java.nio.file.StandardOpenOption;
+
 
 /**
  * Keys in a map of options, together with static constants for commonly-used options.
@@ -33,7 +37,7 @@ import org.apache.sis.util.logging.Loggi
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.4
  * @module
  */
 public class OptionKey<T> implements Serializable {
@@ -45,10 +49,10 @@ public class OptionKey<T> implements Ser
     /**
      * The encoding of a URL (<strong>not</strong> the encoding of the document
content).
      * This option may be used when converting a {@link String} or a {@link java.net.URL}
-     * to a {@link java.net.URI} or a {@link java.io.File}:
+     * to a {@link java.net.URI} or a {@link java.io.File}. The following rules apply:
      *
      * <ul>
-     *   <li>URI are always encoded in UTF-8.</li>
+     *   <li>URI are always encoded in UTF-8. Consequently this option is ignored for
URI.</li>
      *   <li>URL are often encoded in UTF-8, but not necessarily. Other encodings are
possible
      *       (while not recommended), or some URL may not be encoded at all.</li>
      * </ul>
@@ -75,6 +79,20 @@ public class OptionKey<T> implements Ser
     public static final OptionKey<String> URL_ENCODING = new OptionKey<>("URL_ENCODING",
String.class);
 
     /**
+     * Whether a storage object (e.g. a {@link org.apache.sis.storage.DataStore}) shall be
opened in read,
+     * write, append or other modes. The main options that can be provided are:
+     *
+     * <table class="sis">
+     *   <tr><th>Value</th>                             <th>Meaning</th></tr>
+     *   <tr><td>{@link StandardOpenOption#READ}</td>   <td>Open
for reading data from the storage object.</td></tr>
+     *   <tr><td>{@link StandardOpenOption#WRITE}</td>  <td>Open
for modifying existing data in the storage object.</td></tr>
+     *   <tr><td>{@link StandardOpenOption#APPEND}</td> <td>Open
for appending new data in the storage object.</td></tr>
+     *   <tr><td>{@link StandardOpenOption#CREATE}</td> <td>Creates
a new storage object (file or database) if it does not exist.</td></tr>
+     * </table>
+     */
+    public static final OptionKey<OpenOption[]> OPEN_OPTIONS = new OptionKey<>("OPEN_OPTIONS",
OpenOption[].class);
+
+    /**
      * The byte buffer to use for input/output operations. Some {@link org.apache.sis.storage.DataStore}
      * implementations allow a byte buffer to be specified, thus allowing users to choose
the buffer
      * {@linkplain ByteBuffer#capacity() capacity}, whether the buffer {@linkplain ByteBuffer#isDirect()

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java?rev=1509300&r1=1509299&r2=1509300&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
[UTF-8] Thu Aug  1 15:33:07 2013
@@ -16,8 +16,6 @@
  */
 package org.apache.sis.storage.netcdf;
 
-import java.util.Set;
-import java.util.Collections;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.lang.reflect.Method;
@@ -34,7 +32,7 @@ import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreProvider;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.DataStoreException;
-import org.apache.sis.storage.OpenOption;
+import org.apache.sis.storage.ProbeResult;
 import org.apache.sis.util.logging.WarningListeners;
 import org.apache.sis.util.ThreadSafe;
 
@@ -98,38 +96,31 @@ public class NetcdfStoreProvider extends
     }
 
     /**
-     * The open options of NetCDF files.
-     */
-    private static final Set<OpenOption> OPTIONS = Collections.<OpenOption>singleton(OpenOption.READ);
-
-    /**
      * Creates a new provider.
      */
     public NetcdfStoreProvider() {
     }
 
     /**
-     * Returns a non-empty set if the given storage appears to be supported by {@link NetcdfStore}.
-     * Returning a non-empty set from this method does not guarantee that reading or writing
will succeed,
+     * 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.
      *
      * @param  storage Information about the storage (URL, stream, {@link ucar.nc2.NetcdfFile}
instance, <i>etc</i>).
-     * @return A non-empty set if the given storage seems to be usable by the {@code NetcdfStore}
instances,
-     *         an empty set if {@code NetcdfStore} will not be able to use the given storage,
-     *         or {@code null} if this method does not have enough information.
+     * @return {@code SUPPORTED} if the given storage seems to be usable by the {@code NetcdfStore}
instances.
      * @throws DataStoreException if an I/O error occurred.
      */
     @Override
-    public Set<OpenOption> getOpenCapabilities(StorageConnector storage) throws DataStoreException
{
+    public ProbeResult canOpen(StorageConnector storage) throws DataStoreException {
         final ByteBuffer buffer = storage.getStorageAs(ByteBuffer.class);
         if (buffer != null) {
             if (buffer.remaining() < Integer.SIZE / Byte.SIZE) {
-                return Collections.singleton(OpenOption.UNKNOWN);
+                return ProbeResult.UNDETERMINED;
             }
             final int header = buffer.getInt(buffer.position());
             if ((header & 0xFFFFFF00) == ChannelDecoder.MAGIC_NUMBER) {
-                return OPTIONS;
+                return ProbeResult.SUPPORTED;
             }
         }
         /*
@@ -140,7 +131,7 @@ public class NetcdfStoreProvider extends
             ensureInitialized();
             final Method method = canOpenFromPath;
             if (method != null) try {
-                return ((Boolean) method.invoke(null, path)) ? OPTIONS : Collections.<OpenOption>emptySet();
+                return ((Boolean) method.invoke(null, path)) ? ProbeResult.SUPPORTED : ProbeResult.UNKNOWN_FORMAT;
             } catch (IllegalAccessException e) {
                 throw new AssertionError(e); // Should never happen, since the method is
public.
             } catch (InvocationTargetException e) {
@@ -158,16 +149,14 @@ public class NetcdfStoreProvider extends
          */
         for (Class<?> type = storage.getStorage().getClass(); type != null; type =
type.getSuperclass()) {
             if (UCAR_CLASSNAME.equals(type.getName())) {
-                return OPTIONS;
+                return ProbeResult.SUPPORTED;
             }
         }
-        return Collections.emptySet();
+        return ProbeResult.UNKNOWN_FORMAT;
     }
 
     /**
-     * Returns a {@link NetcdfStore} implementation associated with this provider. This method
invokes
-     * {@link StorageConnector#closeAllExcept(Object)} after data store creation, keeping
open only
-     * the needed resource.
+     * Returns a {@link NetcdfStore} implementation associated with this provider.
      *
      * @param storage Information about the storage (URL, stream, {@link ucar.nc2.NetcdfFile}
instance, <i>etc</i>).
      */

Modified: sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java?rev=1509300&r1=1509299&r2=1509300&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java
[UTF-8] Thu Aug  1 15:33:07 2013
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.storage.netcdf;
 
-import java.util.Collections;
 import java.io.IOException;
 import ucar.nc2.NetcdfFile;
 import org.opengis.wrapper.netcdf.IOTestCase;
@@ -25,7 +24,7 @@ import org.apache.sis.internal.netcdf.De
 import org.apache.sis.internal.netcdf.ucar.DecoderWrapper;
 import org.apache.sis.internal.netcdf.impl.ChannelDecoder;
 import org.apache.sis.internal.netcdf.impl.ChannelDecoderTest;
-import org.apache.sis.storage.OpenOption;
+import org.apache.sis.storage.ProbeResult;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.test.DependsOn;
@@ -47,7 +46,7 @@ import static org.opengis.test.Assert.*;
 })
 public final strictfp class NetcdfStoreProviderTest extends IOTestCase {
     /**
-     * Tests {@link NetcdfStoreProvider#getOpenCapabilities(StorageConnector)} for an input
stream which shall
+     * Tests {@link NetcdfStoreProvider#canOpen(StorageConnector)} for an input stream which
shall
      * be recognized as a classic NetCDF file.
      *
      * @throws DataStoreException Should never happen.
@@ -56,12 +55,12 @@ public final strictfp class NetcdfStoreP
     public void testCanOpenFromStream() throws DataStoreException {
         final StorageConnector c = new StorageConnector(IOTestCase.class.getResourceAsStream(NCEP));
         final NetcdfStoreProvider provider = new NetcdfStoreProvider();
-        assertEquals(Collections.singleton(OpenOption.READ), provider.getOpenCapabilities(c));
+        assertEquals(ProbeResult.SUPPORTED, provider.canOpen(c));
         c.closeAllExcept(null);
     }
 
     /**
-     * Tests {@link NetcdfStoreProvider#getOpenCapabilities(StorageConnector)} for a UCAR
{@link NetcdfFile} object.
+     * Tests {@link NetcdfStoreProvider#canOpen(StorageConnector)} for a UCAR {@link NetcdfFile}
object.
      *
      * @throws IOException If an error occurred while opening the NetCDF file.
      * @throws DataStoreException Should never happen.
@@ -71,7 +70,7 @@ public final strictfp class NetcdfStoreP
         final NetcdfFile file = open(NCEP);
         final StorageConnector c = new StorageConnector(file);
         final NetcdfStoreProvider provider = new NetcdfStoreProvider();
-        assertEquals(Collections.singleton(OpenOption.READ), provider.getOpenCapabilities(c));
+        assertEquals(ProbeResult.SUPPORTED, provider.canOpen(c));
         file.close();
     }
 

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=1509300&r1=1509299&r2=1509300&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] Thu Aug  1 15:33:07 2013
@@ -28,6 +28,7 @@ import java.net.URISyntaxException;
 import java.net.MalformedURLException;
 import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
+import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Exceptions;
 import org.apache.sis.util.Static;
@@ -37,7 +38,9 @@ import org.apache.sis.util.resources.Err
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
 import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.OpenOption;
 import java.nio.charset.StandardCharsets;
 
 
@@ -53,7 +56,7 @@ import java.nio.charset.StandardCharsets
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Johann Sorel (Geomatys)
  * @since   0.3 (derived from geotk-3.00)
- * @version 0.3
+ * @version 0.4
  * @module
  */
 public final class IOUtilities extends Static {
@@ -337,10 +340,6 @@ public final class IOUtilities extends S
      * A URL can represent a file, but {@link URL#openStream()} appears to return a {@code
BufferedInputStream}
      * wrapping the {@link FileInputStream}, which is not a desirable feature when we want
to obtain a channel.
      *
-     * <p>There is no {@code toPathOrURL} methods because {@link Path} can be associated
to various file systems.
-     * It would be possible (not necessarily desirable, but at least doable) do create {@code
Path} for HTTP or
-     * FTP protocols.</p>
-     *
      * @param  path The path to convert, or {@code null}.
      * @param  encoding If the URL is encoded in a {@code application/x-www-form-urlencoded}
      *         MIME format, the character encoding (normally {@code "UTF-8"}). If the URL
is
@@ -366,8 +365,11 @@ public final class IOUtilities extends S
             }
         }
         final URL url = new URL(path);
-        if (url.getProtocol().equalsIgnoreCase("file")) {
-            return toFile(url, encoding);
+        final String scheme = url.getProtocol();
+        if (scheme != null) {
+            if (scheme.equalsIgnoreCase("file")) {
+                return toFile(url, encoding);
+            }
         }
         return url;
     }
@@ -384,15 +386,20 @@ public final class IOUtilities extends S
      *       or {@link CharSequence}, then a new channel is opened.</li>
      * </ul>
      *
+     * The given options are used for opening the channel on a <em>best effort basis</em>.
+     * In particular, even if the caller provided the {@code WRITE} option, he still needs
+     * to verify if the returned channel implements {@link java.nio.channels.WritableByteChannel}.
+     *
      * @param  input The file to open, or {@code null}.
      * @param  encoding If the URL is encoded in a {@code application/x-www-form-urlencoded}
      *         MIME format, the character encoding (normally {@code "UTF-8"}). If the URL
is
      *         not encoded, then {@code null}. This argument is ignored if the given path
does
      *         not need to be converted from URL to {@code File}.
+     * @param  options The options to use for creating a new byte channel, or an empty set
for read-only.
      * @return The input stream for the given file, or {@code null} if the given type is
unknown.
      * @throws IOException If an error occurred while opening the given file.
      */
-    public static ReadableByteChannel open(Object input, final String encoding) throws IOException
{
+    public static ReadableByteChannel open(Object input, final String encoding, OpenOption...
options) throws IOException {
         if (input instanceof ReadableByteChannel) {
             return (ReadableByteChannel) input;
         }
@@ -407,21 +414,68 @@ public final class IOUtilities extends S
             }
             return Channels.newChannel((InputStream) input);
         }
-        if (input instanceof Path) {
-            return Files.newByteChannel((Path) input);
-        }
+        /*
+         * In the following cases, we will try hard to convert to Path objects before to
fallback
+         * on File, URL or URI, because only Path instances allow us to use the given OpenOptions.
+         */
         if (input instanceof CharSequence) { // Needs to be before the check for File or
URL.
             input = toFileOrURL(input.toString(), encoding);
         }
+        /*
+         * If the input is a File or a CharSequence that we have been able to convert to
a File,
+         * try to convert to a Path in order to be able to use the OpenOptions. Only if we
fail
+         * to convert to a Path (which is unlikely), we will use directly the File.
+         */
         if (input instanceof File) {
-            return new FileInputStream((File) input).getChannel();
+            try {
+                input = ((File) input).toPath();
+            } catch (InvalidPathException e) {
+                // Unlikely to happen. But if it happens anyway, try to open the channel
in a
+                // way less surprising for the user (closer to the object he has specified).
+                final ReadableByteChannel channel;
+                try {
+                    channel = new FileInputStream((File) input).getChannel();
+                } catch (IOException ioe) {
+                    ioe.addSuppressed(e);
+                    throw ioe;
+                }
+                // We have been able to create a channel, maybe not with the given OpenOptions.
+                // But the exception was nevertheless unexpected, so log its stack trace
in order
+                // to allow the developer to check if there is something wrong.
+                Logging.unexpectedException(Logging.getLogger("org.apache.sis.storage"),
IOUtilities.class, "open", e);
+                return channel;
+            }
         }
+        /*
+         * If the user gave us a URI, try again to convert to a Path for the same reasons
than the above File case.
+         * A failure here is much more likely than in the File case, because JDK7 does not
provide file systems for
+         * HTTP or FTP protocols by default.
+         */
         if (input instanceof URI) { // Needs to be before the check for URL.
-            input = ((URI) input).toURL();
+            final URI uri = (URI) input;
+            try {
+                input = Paths.get(uri);
+            } catch (IllegalArgumentException | FileSystemNotFoundException e) {
+                try {
+                    input = uri.toURL();
+                } catch (IOException ioe) {
+                    ioe.addSuppressed(e);
+                    throw ioe;
+                }
+                // We have been able to create a channel, maybe not with the given OpenOptions.
+                // Log the exception at a fine level and without stack trace, because it
was probably normal.
+                Logging.recoverableException(Logging.getLogger("org.apache.sis.storage"),
IOUtilities.class, "open", e);
+            }
         }
         if (input instanceof URL) {
             return Channels.newChannel(((URL) input).openStream());
         }
+        if (input instanceof Path) {
+            if (options == null) {
+                options = new OpenOption[0];
+            }
+            return Files.newByteChannel((Path) input, options);
+        }
         return null;
     }
 }

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java?rev=1509300&r1=1509299&r2=1509300&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
[UTF-8] Thu Aug  1 15:33:07 2013
@@ -61,90 +61,73 @@ public abstract class DataStoreProvider 
     }
 
     /**
-     * Indicates how the given storage can be opened.
-     * The set returned by this method will fall in one of the following cases:
+     * Indicates if the given storage appears to be supported by the {@code DataStore}s created
by this provider.
+     * The most typical return values are:
      *
      * <ul>
-     *   <li>If the {@code DataStore} managed by this provider can not open the given
storage,
-     *       then this method returns an empty set.</li>
-     *   <li>Otherwise if this method does not have enough information for determining
the
-     *       open capabilities, then this method returns a singleton containing only the
-     *       {@link OpenOption#UNKNOWN} value.</li>
-     *   <li>Otherwise this method returns a set containing at least one, and possibly
many, of
-     *       {@link OpenOption#READ}, {@link OpenOption#WRITE WRITE}, {@link OpenOption#APPEND
APPEND},
-     *       {@link OpenOption#CREATE CREATE} or implementation-specific values.</li>
+     *   <li>{@link ProbeResult#SUPPORTED} if the {@code DataStore}s created by this
provider
+     *       can open the given storage.</li>
+     *   <li>{@link ProbeResult#UNKNOWN_STORAGE} if the given storage does not appear
to be in a format
+     *       supported by this {@code DataStoreProvider}.</li>
      * </ul>
      *
-     * Note that the later case does not guarantee that reading or writing will succeed,
+     * Note that the {@code SUPPORTED_FORMAT} value 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.
      *
-     * {@section Implementation note}
+     * Implementors are responsible for restoring the input to its original stream position
on return of this method.
+     * Implementors can use a mark/reset pair for this purpose. Marks are available as
+     * {@link java.nio.ByteBuffer#mark()}, {@link java.io.InputStream#mark(int)} and
+     * {@link javax.imageio.stream.ImageInputStream#mark()}.
+     *
+     * {@section Implementation example}
      * Implementations will typically check the first bytes of the stream for a "magic number"
associated
      * with the format, as in the following example:
      *
      * {@preformat java
-     *     public Set<OpenOption> getOpenCapabilities(StorageConnector storage) throws
DataStoreException {
+     *     public ProbeResult canOpen(StorageConnector storage) throws DataStoreException
{
      *         final ByteBuffer buffer = storage.getStorageAs(ByteBuffer.class);
-     *         if (buffer != null) {
-     *             if (buffer.remaining() < Integer.SIZE / Byte.SIZE) {
-     *                 return Collections.singleton(OpenOption.UNKNOWN);
-     *             }
-     *             if (buffer.getInt(buffer.position()) == MAGIC_NUMBER) {
-     *                 return Collections.singleton(OpenOption.READ);
-     *             }
+     *         if (buffer == null) {
+     *             // If StorageConnector can not provide a ByteBuffer, then the storage
is
+     *             // probably not a File, URL, URI, InputStream neither a ReadableChannel.
+     *             return ProbeResult.UNKNOWN_STORAGE;
      *         }
-     *         return Collections.emptySet();
+     *         if (buffer.remaining() < Integer.SIZE / Byte.SIZE) {
+     *             // If the buffer does not contain enough bytes for the integer type, this
is not
+     *             // necessarily because the file is truncated. It may be because the data
were not
+     *             // yet available at the time this method has been invoked.
+     *             return ProbeResult.UNDETERMINED;
+     *         }
+     *         if (buffer.getInt(buffer.position()) != MAGIC_NUMBER) {
+     *             // We used ByteBuffer.getInt(int) instead than ByteBuffer.getInt() above
+     *             // in order to keep the buffer position unchanged after this method call.
+     *             return ProbeResult.UNKNOWN_FORMAT;
+     *         }
+     *         return ProbeResult.SUPPORTED;
      *     }
      * }
      *
-     * {@note <ul>
-     *   <li>If <code>StorageConnector</code> can not provide a <code>ByteBuffer</code>,
then the storage is
-     *       probably not a <code>File</code>, <code>URL</code>,
<code>URI</code>, <code>InputStream</code>
-     *       neither a <code>ReadableChannel</code>. In the above example, our
provider can not handle such
-     *       unknown source.</li>
-     *   <li>Above example uses <code>ByteBuffer.getInt(int)</code> instead
than <code>ByteBuffer.getInt()</code>
-     *       in order to keep the buffer position unchanged after this method call.</li>
-     *   <li>If the buffer does not contain enough bytes for the <code>int</code>
type, this is not necessarily
-     *       because the file is truncated. It may be because the data were not yet available
at the time this
-     *       method has been invoked. Returning <code>null</code> means "don't
know".</li>
-     * </ul>}
-     *
-     * Implementors are responsible for restoring the input to its original stream position
on return of this method.
-     * Implementors can use a mark/reset pair for this purpose. Marks are available as
-     * {@link java.nio.ByteBuffer#mark()}, {@link java.io.InputStream#mark(int)} and
-     * {@link javax.imageio.stream.ImageInputStream#mark()}.
-     *
      * @param  storage Information about the storage (URL, stream, JDBC connection, <i>etc</i>).
-     * @return A non-empty set if the given storage seems to be usable by the {@code DataStore}
instances
-     *         create by this provider, an empty set if the {@code DataStore} will not be
able to use
-     *         the given storage, or {@code null} if this method does not have enough information.
+     * @return {@link ProbeResult#SUPPORTED} 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.
-     *
-     * @since 0.4
-     */
-    public abstract Set<OpenOption> getOpenCapabilities(StorageConnector storage) throws
DataStoreException;
-
-    /**
-     * @deprecated Replaced by {@link #getOpenCapabilities(StorageConnector)}.
      */
-    @Deprecated
-    public Boolean canOpen(StorageConnector storage) throws DataStoreException {
-        final Set<OpenOption> options = getOpenCapabilities(storage);
-        return (options == null) ? null : options.contains(OpenOption.READ);
-    }
+    public abstract ProbeResult canOpen(StorageConnector storage) throws DataStoreException;
 
     /**
      * Returns a data store implementation associated with this provider.
      *
-     * <p><b>Implementation note:</b>
+     * {@section Implementation note}
      * Implementors shall invoke {@link StorageConnector#closeAllExcept(Object)} after {@code
DataStore}
-     * creation, keeping open only the needed resource.</p>
+     * creation, keeping open only the needed resource.
      *
      * @param  storage Information about the storage (URL, stream, JDBC connection, <i>etc</i>).
      * @return A data store implementation associated with this provider for the given storage.
-     * @throws DataStoreException if an error occurred while creating the data store instance.
+     * @throws IllegalArgumentException If the set contains an invalid combination of options.
+     * @throws DataStoreException If an error occurred while creating the data store instance.
+     *
+     * @see DataStores#open(Object, Set)
      */
     public abstract DataStore open(StorageConnector storage) throws DataStoreException;
 }

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java?rev=1509300&r1=1509299&r2=1509300&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java
[UTF-8] Thu Aug  1 15:33:07 2013
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.storage;
 
-import java.util.Set;
 import java.util.ServiceLoader;
 import org.apache.sis.util.ThreadSafe;
 import org.apache.sis.util.ArgumentChecks;
@@ -78,21 +77,12 @@ final class DataStoreRegistry {
      * </ul>
      *
      * @param  storage The input/output object as a URL, file, image input stream, <i>etc.</i>.
-     * @param  options The open options. Shall contain at least one element, typically {@link
OpenOption#READ}.
      * @return The object to use for reading geospatial data from the given storage.
      * @throws UnsupportedStorageException if no {@link DataStoreProvider} is found for a
given storage object.
      * @throws DataStoreException If an error occurred while opening the storage.
      */
-    public DataStore open(final Object storage, final Set<OpenOption> options) throws
DataStoreException {
+    public DataStore open(final Object storage) throws DataStoreException {
         ArgumentChecks.ensureNonNull("storage", storage);
-        ArgumentChecks.ensureNonNull("options", options);
-        if (options.isEmpty()) {
-            throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyArgument_1,
"options"));
-        }
-        if (options.contains(OpenOption.UNKNOWN)) {
-            throw new IllegalArgumentException(Errors.format(
-                    Errors.Keys.IllegalArgumentValue_2, "options", OpenOption.UNKNOWN));
-        }
         StorageConnector connector;
         if (storage instanceof StorageConnector) {
             connector = (StorageConnector) storage;
@@ -102,13 +92,16 @@ final class DataStoreRegistry {
         try {
             DataStoreProvider provider = null;
             synchronized (loader) {
-                for (final DataStoreProvider candidate : loader) {
-                    final Set<OpenOption> capabilities = candidate.getOpenCapabilities(connector);
-                    if (capabilities.contains(OpenOption.UNKNOWN)) {
-                        // TODO: not enough information.
-                    } else if (capabilities.containsAll(options)) {
-                        provider = candidate;
-                        break;
+search:         for (final DataStoreProvider candidate : loader) {
+                    switch (candidate.canOpen(connector)) {
+                        case SUPPORTED: {
+                            provider = candidate;
+                            break search;
+                        }
+                        case UNDETERMINED: {
+                            // TODO: not enough information.
+                            break;
+                        }
                     }
                 }
             }

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java?rev=1509300&r1=1509299&r2=1509300&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java
[UTF-8] Thu Aug  1 15:33:07 2013
@@ -16,8 +16,6 @@
  */
 package org.apache.sis.storage;
 
-import java.util.Set;
-import java.util.Collections;
 import org.apache.sis.util.Static;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.system.SystemListener;
@@ -58,44 +56,13 @@ public final class DataStores extends St
     }
 
     /**
-     * The options for opening storage in read mode.
-     */
-    private static final Set<OpenOption> READ = Collections.singleton(OpenOption.READ);
-
-    /**
      * Do not allow instantiation of this class.
      */
     private DataStores() {
     }
 
     /**
-     * Creates a {@link DataStore} for the given storage using its default set of {@code
OpenOption}s.
-     * The data store is guaranteed to be opened at least with {@link OpenOption#READ}.
-     * Whether the data store has also write or append capabilities is implementation dependent.
-     *
-     * <p>The {@code storage} argument can be any of the following types:</p>
-     *
-     * <ul>
-     *   <li>A {@link java.nio.file.Path} or a {@link java.io.File} for a file or a
directory.</li>
-     *   <li>A {@link java.net.URI} or a {@link java.net.URL} to a distant resource.</li>
-     *   <li>A {@link java.lang.CharSequence} interpreted as a filename or a URL.</li>
-     *   <li>A {@link java.nio.channels.Channel} or a {@link java.io.DataInput}.</li>
-     *   <li>A {@link javax.sql.DataSource} or a {@link java.sql.Connection} to a JDBC
database.</li>
-     *   <li>Any other {@code DataStore}-specific object, for example {@link ucar.nc2.NetcdfFile}.</li>
-     *   <li>An existing {@link StorageConnector} instance.</li>
-     * </ul>
-     *
-     * @param  storage The input/output object as a URL, file, image input stream, <i>etc.</i>.
-     * @return The object to use for reading geospatial data from the given storage.
-     * @throws UnsupportedStorageException if no {@link DataStoreProvider} is found for a
given storage object.
-     * @throws DataStoreException If an error occurred while opening the storage.
-     */
-    public static DataStore open(final Object storage) throws DataStoreException {
-        return open(storage, READ);
-    }
-
-    /**
-     * Creates a {@link DataStore} for the given storage using the given set of {@code OpenOption}s.
+     * Creates a {@link DataStore} for the given storage.
      * The {@code storage} argument can be any of the following types:
      *
      * <ul>
@@ -109,12 +76,11 @@ public final class DataStores extends St
      * </ul>
      *
      * @param  storage The input/output object as a URL, file, image input stream, <i>etc.</i>.
-     * @param  options The open options. Shall contain at least one element, typically {@link
OpenOption#READ}.
      * @return The object to use for reading geospatial data from the given storage.
      * @throws UnsupportedStorageException if no {@link DataStoreProvider} is found for a
given storage object.
      * @throws DataStoreException If an error occurred while opening the storage.
      */
-    public static DataStore open(final Object storage, final Set<OpenOption> options)
throws DataStoreException {
+    public static DataStore open(final Object storage) throws DataStoreException {
         DataStoreRegistry r = registry;
         if (r == null) {
             synchronized (DataStores.class) {
@@ -124,6 +90,6 @@ public final class DataStores extends St
                 }
             }
         }
-        return r.open(storage, options);
+        return r.open(storage);
     }
 }

Copied: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java
(from r1509040, sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/OpenOption.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java?p2=sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java&p1=sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/OpenOption.java&r1=1509040&r2=1509300&rev=1509300&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/OpenOption.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java
[UTF-8] Thu Aug  1 15:33:07 2013
@@ -16,71 +16,43 @@
  */
 package org.apache.sis.storage;
 
-import java.util.List;
-import java.util.ArrayList;
-import org.opengis.util.CodeList;
-
 
 /**
- * Specifies how to open a {@link DataStore}.
- * This code list serves a similar purpose than the {@code java.nio.file} {@link java.nio.file.OpenOption},
- * except that it applies to data stores instead than files. The options provided by this
code list are very
- * similar to the {@code java.nio.file} ones except for {@link #UNKNOWN}.
+ * Tells whether a storage (file, database, <i>etc.</i>) appears to be supported
by a {@code DataStore}.
+ * There is three categories of values in this enumeration:
+ *
+ * <ul>
+ *   <li>{@link #SUPPORTED} indicates that the storage can be read and eventually written.</li>
+ *   <li>{@link #UNDETERMINED} indicates that the provider does not have enough information
for telling
+ *       whether the storage can be opened. SIS will try to use such provider last, if no
better suited
+ *       provider is found.</li>
+ *   <li>All other values indicate that the storage can not be opened. The actual enumeration
value gives
+ *       the reason (e.g. unknown format, or unsupported version).</li>
+ * </ul>
  *
- * <p>This code list is extensible: some {@code DataStore} subclasses may provide their
own implementation
- * specific open options.</p>
+ * When a {@link DataStores#open DataStores.open(…)} method is invoked, SIS will iterate
over the list of known
+ * providers and invoke the {@link DataStoreProvider#canOpen(StorageConnector)} method for
each of them.
+ * The {@code ProbeResult} value returned by {@code canOpen(…)} tells to SIS whether a
particular
+ * {@code DataStoreProvider} instance has reasonable chances to be able to handle the given
storage.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
  * @version 0.4
  * @module
  *
- * @see java.nio.file.OpenOption
+ * @see DataStoreProvider#canOpen(StorageConnector)
  */
-public final class OpenOption extends CodeList<OpenOption> {
-    /**
-     * For cross-version compatibility.
-     */
-    private static final long serialVersionUID = -892034640198004572L;
-
+public enum ProbeResult {
     /**
-     * List of all enumerations of this type.
-     * Shall be declared before any enum declaration.
+     * The {@code DataStoreProvider} recognizes the given storage.
+     * {@code DataStore} instances created by that provider are likely (but not guaranteed)
+     * to be able to read from - and eventually write to - the given storage.
      */
-    private static final List<OpenOption> VALUES = new ArrayList<>(5);
+    SUPPORTED,
 
     /**
-     * Open for reading data from a {@link DataStore}.
-     *
-     * @see java.nio.file.StandardOpenOption#READ
-     */
-    public static final OpenOption READ = new OpenOption("READ");
-
-    /**
-     * Open for overwriting existing data in a {@link DataStore}.
-     *
-     * @see java.nio.file.StandardOpenOption#WRITE
-     */
-    public static final OpenOption WRITE = new OpenOption("WRITE");
-
-    /**
-     * Open for appending new data in a {@link DataStore}.
-     *
-     * @see java.nio.file.StandardOpenOption#APPEND
-     */
-    public static final OpenOption APPEND = new OpenOption("APPEND");
-
-    /**
-     * Creates a new file or database if it does not exist.
-     *
-     * @see java.nio.file.StandardOpenOption#CREATE
-     */
-    public static final OpenOption CREATE = new OpenOption("CREATE");
-
-    /**
-     * Indicates that the open capabilities can not be determined.
-     * This value may be returned by {@linkplain DataStoreProvider#getOpenCapabilities(StorageConnector)}
-     * in two kind of situations:
+     * The open capability can not be determined.
+     * This value may be returned in two kinds of situation:
      *
      * <ul>
      *   <li>The method can not look ahead far enough in the file header,
@@ -88,54 +60,25 @@ public final class OpenOption extends Co
      *   <li>The {@code DataStore} could potentially open anything.
      *       This is the case for example of the RAW image format.</li>
      * </ul>
-     *
-     * This option is exclusive with all other options.
      */
-    public static final OpenOption UNKNOWN = new OpenOption("UNKNOWN");
+    UNDETERMINED,
 
     /**
-     * Creates a new code list element of the given name.
-     * The new element is automatically added to the {@link #VALUES} list.
-     *
-     * @param name The name of the new element. Must be unique in this code list.
+     * The {@code DataStoreProvider} does not recognize the given storage object.
+     * For example the storage may be a file while the provider expected a database connection,
or conversely.
      */
-    private OpenOption(final String name) {
-        super(name, VALUES);
-    }
+    UNKNOWN_STORAGE,
 
     /**
-     * Returns the list of {@code OpenOption}s.
-     *
-     * @return The list of open options declared in the current JVM.
+     * The {@code DataStoreProvider} does not recognize the file format or schema.
+     * For example the file does not contains the expected magic number,
+     * or the database schema does not contain the expected tables.
      */
-    public static OpenOption[] values() {
-        synchronized (VALUES) {
-            return VALUES.toArray(new OpenOption[VALUES.size()]);
-        }
-    }
+    UNKNOWN_FORMAT,
 
     /**
-     * Returns the list of codes of the same kind than this code list element.
-     * Invoking this method is equivalent to invoking {@link #values()}, except that
-     * this method can be invoked on an instance of the parent {@code CodeList} class.
-     *
-     * @return The list of open options declared in the current JVM.
-     */
-    @Override
-    public OpenOption[] family() {
-        return values();
-    }
-
-    /**
-     * Returns the open option that matches the given string, or returns a new one if none
match it.
-     * More specifically, this methods returns the first instance for which
-     * <code>{@linkplain #name() name()}.{@linkplain String#equals equals}(code)</code>
returns {@code true}.
-     * If no existing instance is found, then a new one is created for the given name.
-     *
-     * @param code The name of the code to fetch or to create.
-     * @return A code matching the given name.
+     * The {@code DataStoreProvider} recognizes the given storage, but the data are structured
+     * according a file or schema version not yet supported by the current implementation.
      */
-    public static OpenOption valueOf(String code) {
-        return valueOf(OpenOption.class, code);
-    }
+    UNSUPPORTED_VERSION
 }

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java?rev=1509300&r1=1509299&r2=1509300&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
[UTF-8] Thu Aug  1 15:33:07 2013
@@ -164,6 +164,7 @@ public class StorageConnector implements
      *
      * <ul>
      *   <li>{@link OptionKey#URL_ENCODING} for converting URL to URI or filename,
if needed.</li>
+     *   <li>{@link OptionKey#OPEN_OPTIONS} for specifying whether the data store shall
be read only or read/write.</li>
      *   <li>{@link OptionKey#BYTE_BUFFER} for allowing users to control the byte buffer
to be created.</li>
      * </ul>
      *
@@ -296,8 +297,8 @@ public class StorageConnector implements
      *
      * Multiple invocations of this method on the same {@code StorageConnector} instance
will try
      * to return the same instance on a <cite>best effort</cite> basis. Consequently,
implementations of
-     * {@link DataStoreProvider#getOpenCapabilities(StorageConnector)} methods shall not
close the stream or
-     * database connection returned by this method. In addition, those {@code getOpenCapabilities(StorageConnector)}
+     * {@link DataStoreProvider#canOpen(StorageConnector)} methods shall not close the stream
or
+     * database connection returned by this method. In addition, those {@code canOpen(StorageConnector)}
      * methods are responsible for restoring the stream or byte buffer to its original position
on return.
      *
      * @param  <T>  The compile-time type of the {@code type} argument.
@@ -368,7 +369,8 @@ public class StorageConnector implements
      * @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));
+        final ReadableByteChannel channel = IOUtilities.open(storage,
+                getOption(OptionKey.URL_ENCODING), getOption(OptionKey.OPEN_OPTIONS));
         ChannelDataInput asDataInput = null;
         if (channel != null) {
             ByteBuffer buffer = getOption(OptionKey.BYTE_BUFFER);



Mime
View raw message