sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1489846 - in /sis/branches/JDK7/storage: sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/ sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/ sis-netcdf/src/test/java...
Date Wed, 05 Jun 2013 13:10:29 GMT
Author: desruisseaux
Date: Wed Jun  5 13:10:29 2013
New Revision: 1489846

URL: http://svn.apache.org/r1489846
Log:
First draft of a DataStoreProvider abstract class, and some tests with NetcdfStoreProvider.

Added:
    sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java
  (with props)
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
  (with props)
Modified:
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.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/test/suite/NetcdfTestSuite.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreConnection.java

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java?rev=1489846&r1=1489845&r2=1489846&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
[UTF-8] Wed Jun  5 13:10:29 2013
@@ -64,6 +64,17 @@ import org.apache.sis.measure.Units;
  */
 public final class ChannelDecoder extends Decoder {
     /**
+     * The NetCDF magic number expected in the first integer of the stream.
+     * The comparison shall ignore the 8 lowest bits, as in the following example:
+     *
+     * {@preformat java
+     *     int header = ...; // The first integer in the stream.
+     *     boolean isNetCDF = (header & 0xFFFFFF00) == MAGIC_NUMBER;
+     * }
+     */
+    public static final int MAGIC_NUMBER = ('C' << 24) | ('D' << 16) | ('F' <<
 8);
+
+    /**
      * The encoding of dimension, variable and attribute names. This is fixed to {@value}
by the
      * NetCDF specification. Note however that the encoding of attribute values may be different.
      *
@@ -188,7 +199,7 @@ public final class ChannelDecoder extend
          * The 4th byte is the version number, which we opportunistically use after the magic
number check.
          */
         int version = input.readInt();
-        if ((version & 0xFFFFFF00) != (('C' << 24) | ('D' << 16) | ('F' <<
 8))) {
+        if ((version & 0xFFFFFF00) != MAGIC_NUMBER) {
             throw new DataStoreException(errors().getString(Errors.Keys.UnexpectedFileFormat_2,
"NetCDF", input.filename));
         }
         /*

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=1489846&r1=1489845&r2=1489846&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] Wed Jun  5 13:10:29 2013
@@ -17,6 +17,8 @@
 package org.apache.sis.storage.netcdf;
 
 import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.lang.reflect.Method;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.UndeclaredThrowableException;
@@ -25,12 +27,14 @@ import org.apache.sis.internal.netcdf.im
 import org.apache.sis.internal.netcdf.ucar.DecoderWrapper;
 import org.apache.sis.internal.storage.ChannelDataInput;
 import org.apache.sis.internal.storage.WarningProducer;
+import org.apache.sis.storage.DataStore;
+import org.apache.sis.storage.DataStoreProvider;
 import org.apache.sis.storage.DataStoreConnection;
 import org.apache.sis.storage.DataStoreException;
 
 
 /**
- * The provider of {@link NetcdfStore} instances. Given an {@link DataStoreConnection} input,
+ * The provider of {@link NetcdfStore} instances. Given a {@link DataStoreConnection} input,
  * this class tries to instantiate a {@code NetcdfStore} using the embedded NetCDF decoder.
  * If the embedded decoder can not decode the given input and the UCAR library is reachable
  * on the classpath, then this class tries to instantiate a {@code NetcdfStore} backed by
@@ -41,7 +45,12 @@ import org.apache.sis.storage.DataStoreE
  * @version 0.3
  * @module
  */
-public class NetcdfStoreProvider {
+public class NetcdfStoreProvider extends DataStoreProvider {
+    /**
+     * The name of the {@link ucar.nc2.NetcdfFile} class, which is {@value}.
+     */
+    private static final String UCAR_CLASSNAME = "ucar.nc2.NetcdfFile";
+
     /**
      * The {@link ucar.nc2.NetcdfFile} class, or {@code null} if not found. An attempt to
load this class
      * will be performed when first needed since the UCAR library is optional. If not found,
then this field
@@ -50,16 +59,22 @@ public class NetcdfStoreProvider {
     private static Class<?> netcdfFileClass;
 
     /**
-     * If the {@link #netcdfFileClass} has been found, then the {@link DecoderWrapper} constructor
receiving
-     * in argument a UCAR {@code NetcdfFile} object. Otherwise {@code null}.
+     * If the {@link #netcdfFileClass} has been found, then the {@link ucar.nc2.NetcdfFile#canOpen(String)}
+     * static method.
      */
-    private static volatile Constructor<? extends Decoder> fromUCAR;
+    private static volatile Method canOpenFromPath;
 
     /**
      * If the {@link #netcdfFileClass} has been found, then the {@link DecoderWrapper} constructor
receiving
      * in argument the name of the NetCDF file as a {@link String} object. Otherwise {@code
null}.
      */
-    private static volatile Constructor<? extends Decoder> fromFilename;
+    private static volatile Constructor<? extends Decoder> createFromPath;
+
+    /**
+     * If the {@link #netcdfFileClass} has been found, then the {@link DecoderWrapper} constructor
receiving
+     * in argument a UCAR {@code NetcdfFile} object. Otherwise {@code null}.
+     */
+    private static volatile Constructor<? extends Decoder> createFromUCAR;
 
     /**
      * Creates a new provider.
@@ -68,6 +83,72 @@ public class NetcdfStoreProvider {
     }
 
     /**
+     * Returns {@code TRUE} if the given storage appears to be supported by {@link NetcdfStore}.
+     * Returning {@code TRUE} 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 DataStoreConnection#getStorage() storage object} or contents.
+     *
+     * @param  storage Information about the storage (URL, stream, {@link ucar.nc2.NetcdfFile}
instance, <i>etc</i>).
+     * @return {@link Boolean#TRUE} if the given storage seems to be usable by the {@code
NetcdfStore} instances,
+     *         {@link Boolean#FALSE} if {@code NetcdfStore} will not be able to use the given
storage,
+     *         or {@code null} if this method does not have enough information.
+     * @throws DataStoreException if an I/O error occurred.
+     */
+    @Override
+    public Boolean canOpen(DataStoreConnection storage) throws DataStoreException {
+        final ByteBuffer buffer = storage.getStorageAs(ByteBuffer.class);
+        if (buffer != null) {
+            if (buffer.remaining() < Integer.SIZE / Byte.SIZE) {
+                return null;
+            }
+            final int header = buffer.getInt(buffer.position());
+            if ((header & 0xFFFFFF00) == ChannelDecoder.MAGIC_NUMBER) {
+                return Boolean.TRUE;
+            }
+        }
+        /*
+         * If we failed to check using the embedded decoder, tries using the UCAR library.
+         */
+        final String path = storage.getStorageAs(String.class);
+        if (path != null) {
+            ensureInitialized();
+            final Method method = canOpenFromPath;
+            if (method != null) try {
+                return (Boolean) method.invoke(null, path);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError(e); // Should never happen, since the method is
public.
+            } catch (InvocationTargetException e) {
+                final Throwable cause = e.getCause();
+                if (cause instanceof DataStoreException) throw (DataStoreException) cause;
+                if (cause instanceof RuntimeException)   throw (RuntimeException)   cause;
+                if (cause instanceof Error)              throw (Error)              cause;
+                throw new DataStoreException(e); // The cause may be IOException.
+            }
+        }
+        /*
+         * Check if the given input is itself an instance of the UCAR oject.
+         * We check classnames instead of netcdfFileClass.isInstance(storage)
+         * in order to avoid loading the UCAR library if not needed.
+         */
+        for (Class<?> type = storage.getStorage().getClass(); type != null; type=type.getSuperclass())
{
+            if (UCAR_CLASSNAME.equals(type.getName())) {
+                return Boolean.TRUE;
+            }
+        }
+        return Boolean.FALSE;
+    }
+
+    /**
+     * 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>).
+     */
+    @Override
+    public DataStore open(DataStoreConnection storage) throws DataStoreException {
+        throw new UnsupportedOperationException("Not supported yet."); // TODO
+    }
+
+    /**
      * Creates a decoder for the given input.
      *
      * @param  sink       Where to send the warnings, or {@code null} if none.
@@ -91,7 +172,7 @@ public class NetcdfStoreProvider {
             }
             throw e;
         }
-        return createByReflection(sink, connection, true);
+        return createByReflection(sink, connection.getStorage(), true);
     }
 
     /**
@@ -110,29 +191,7 @@ public class NetcdfStoreProvider {
     private static Decoder createByReflection(final WarningProducer sink, final Object input,
final boolean isUCAR)
             throws IOException, DataStoreException
     {
-        /*
-         * Get the java.lang.Class that represent the ucar.nc2.NetcdfFile type. We do not
synchronize since it
-         * is not a big deal if Class.forName(…) is invoked twice. The Class.forName(…)
method performs itself
-         * the required synchronization for returning the same singleton Class instance.
-         */
-        if (netcdfFileClass == null) {
-            try {
-                netcdfFileClass = Class.forName("ucar.nc2.NetcdfFile");
-            } catch (ClassNotFoundException e) {
-                netcdfFileClass = Void.TYPE;
-                return null;
-            }
-            try {
-                final Class<? extends Decoder> wrapper =
-                        Class.forName("org.apache.sis.internal.netcdf.ucar.DecoderWrapper").asSubclass(Decoder.class);
-                final Class<?>[] parameterTypes = new Class<?>[] {WarningProducer.class,
netcdfFileClass};
-                fromUCAR = wrapper.getConstructor(parameterTypes);
-                parameterTypes[1] = String.class;
-                fromFilename = wrapper.getConstructor(parameterTypes);
-            } catch (ReflectiveOperationException e) {
-                throw new AssertionError(e); // Should never happen (shall be verified by
the JUnit tests).
-            }
-        }
+        ensureInitialized();
         /*
          * Get the appropriate constructor for the isUCAR argument. This constructor will
be null
          * if the above code failed to load the UCAR library. Otherwise, instantiate the
wrapper.
@@ -140,10 +199,10 @@ public class NetcdfStoreProvider {
         final Constructor<? extends Decoder> constructor;
         final Class<?> expectedType;
         if (isUCAR) {
-            constructor  = fromUCAR;
+            constructor  = createFromUCAR;
             expectedType = netcdfFileClass;
         } else {
-            constructor  = fromFilename;
+            constructor  = createFromPath;
             expectedType = String.class;
         }
         if (constructor == null || !expectedType.isInstance(input)) {
@@ -162,4 +221,39 @@ public class NetcdfStoreProvider {
             throw new AssertionError(e); // Should never happen (shall be verified by the
JUnit tests).
         }
     }
+
+    /**
+     * Get the {@link java.lang.Class} that represent the {@link ucar.nc2.NetcdfFile type}.
+     * We do not synchronize this method since it is not a big deal if {@code Class.forName(…)}
is invoked twice.
+     * The {@code Class.forName(…)} method performs itself the required synchronization
for returning the same
+     * singleton {@code Class} instance.
+     */
+    private static void ensureInitialized() {
+        if (netcdfFileClass == null) {
+            try {
+                netcdfFileClass = Class.forName(UCAR_CLASSNAME);
+            } catch (ClassNotFoundException e) {
+                netcdfFileClass = Void.TYPE;
+                return;
+            }
+            try {
+                /*
+                 * UCAR API.
+                 */
+                canOpenFromPath = netcdfFileClass.getMethod("canOpen", String.class);
+                assert canOpenFromPath.getReturnType() == Boolean.TYPE;
+                /*
+                 * SIS Wrapper API.
+                 */
+                final Class<? extends Decoder> wrapper =
+                        Class.forName("org.apache.sis.internal.netcdf.ucar.DecoderWrapper").asSubclass(Decoder.class);
+                final Class<?>[] parameterTypes = new Class<?>[] {WarningProducer.class,
netcdfFileClass};
+                createFromUCAR = wrapper.getConstructor(parameterTypes);
+                parameterTypes[1] = String.class;
+                createFromPath = wrapper.getConstructor(parameterTypes);
+            } catch (ReflectiveOperationException e) {
+                throw new AssertionError(e); // Should never happen (shall be verified by
the JUnit tests).
+            }
+        }
+    }
 }

Added: 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=1489846&view=auto
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java
(added)
+++ sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java
[UTF-8] Wed Jun  5 13:10:29 2013
@@ -0,0 +1,105 @@
+/*
+ * 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.storage.netcdf;
+
+import java.io.IOException;
+import ucar.nc2.NetcdfFile;
+import org.opengis.wrapper.netcdf.IOTestCase;
+import org.apache.sis.internal.netcdf.Decoder;
+import org.apache.sis.internal.netcdf.impl.ChannelDecoder;
+import org.apache.sis.internal.netcdf.ucar.DecoderWrapper;
+import org.apache.sis.internal.netcdf.impl.ChannelDecoderTest;
+import org.apache.sis.storage.DataStoreConnection;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.test.DependsOn;
+import org.junit.Test;
+
+import static org.opengis.test.Assert.*;
+import static org.opengis.wrapper.netcdf.IOTestCase.NCEP;
+
+
+/**
+ * Tests {@link NetcdfStoreProvider}.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3
+ * @version 0.3
+ * @module
+ */
+@DependsOn({
+    ChannelDecoderTest.class
+})
+public final strictfp class NetcdfStoreProviderTest extends IOTestCase {
+    /**
+     * Tests {@link NetcdfStoreProvider#canOpen(DataStoreConnection)} for an input stream
which shall
+     * be recognized as a classic NetCDF file.
+     *
+     * @throws DataStoreException Should never happen.
+     */
+    @Test
+    public void testCanOpenFromStream() throws DataStoreException {
+        final DataStoreConnection c = new DataStoreConnection(IOTestCase.class.getResourceAsStream(NCEP));
+        final NetcdfStoreProvider provider = new NetcdfStoreProvider();
+        assertTrue(provider.canOpen(c));
+        c.closeAllExcept(null);
+    }
+
+    /**
+     * Tests {@link NetcdfStoreProvider#canOpen(DataStoreConnection)} for a UCAR {@link NetcdfFile}
object.
+     *
+     * @throws IOException If an error occurred while opening the NetCDF file.
+     * @throws DataStoreException Should never happen.
+     */
+    @Test
+    public void testCanOpenFromUCAR() throws IOException, DataStoreException {
+        final NetcdfFile file = open(NCEP);
+        final DataStoreConnection c = new DataStoreConnection(file);
+        final NetcdfStoreProvider provider = new NetcdfStoreProvider();
+        assertTrue(provider.canOpen(c));
+        file.close();
+    }
+
+    /**
+     * Tests {@link NetcdfStoreProvider#decoder(WarningProducer, DataStoreConnection)} for
an input stream which
+     * shall be recognized as a classic NetCDF file. The provider shall instantiate a {@link
ChannelDecoder}.
+     *
+     * @throws IOException If an error occurred while opening the NetCDF file.
+     * @throws DataStoreException Should never happen.
+     */
+    @Test
+    public void testDecoderFromStream() throws IOException, DataStoreException {
+        final DataStoreConnection c = new DataStoreConnection(IOTestCase.class.getResourceAsStream(NCEP));
+        final Decoder decoder = NetcdfStoreProvider.decoder(null, c);
+        assertInstanceOf(NCEP, ChannelDecoder.class, decoder);
+        decoder.close();
+    }
+
+    /**
+     * Tests {@link NetcdfStoreProvider#decoder(WarningProducer, DataStoreConnection)} for
a UCAR
+     * {@link NetcdfFile} object. The provider shall instantiate a {@link DecoderWrapper}.
+     *
+     * @throws IOException If an error occurred while opening the NetCDF file.
+     * @throws DataStoreException Should never happen.
+     */
+    @Test
+    public void testDecoderFromUCAR() throws IOException, DataStoreException {
+        final DataStoreConnection c = new DataStoreConnection(open(NCEP));
+        final Decoder decoder = NetcdfStoreProvider.decoder(null, c);
+        assertInstanceOf(NCEP, DecoderWrapper.class, decoder);
+        decoder.close();
+    }
+}

Propchange: sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/test/suite/NetcdfTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/test/suite/NetcdfTestSuite.java?rev=1489846&r1=1489845&r2=1489846&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/test/suite/NetcdfTestSuite.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/test/suite/NetcdfTestSuite.java
[UTF-8] Wed Jun  5 13:10:29 2013
@@ -39,7 +39,8 @@ import org.junit.BeforeClass;
     org.apache.sis.internal.netcdf.impl.VariableInfoTest.class,
     org.apache.sis.internal.netcdf.impl.GridGeometryInfoTest.class,
     org.apache.sis.storage.netcdf.MetadataReaderTest.class,
-    org.apache.sis.storage.netcdf.ConformanceTest.class
+    org.apache.sis.storage.netcdf.ConformanceTest.class,
+    org.apache.sis.storage.netcdf.NetcdfStoreProviderTest.class
 })
 public final strictfp class NetcdfTestSuite extends TestSuite {
     /**

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=1489846&r1=1489845&r2=1489846&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] Wed Jun  5 13:10:29 2013
@@ -295,8 +295,8 @@ public class DataStoreConnection impleme
      *
      * Multiple invocations of this method on the same {@code DataStoreConnection} instance
will try
      * to return the same instance on a <cite>best effort</cite> basis. Consequently,
implementations
-     * of {@link DataStoreProvider#canRead(DataStoreConnection)} methods shall not close
the stream or
-     * database connection returned by this method. In addition, those {@code canRead(DataStoreConnection)}
+     * of {@link DataStoreProvider#canOpen(DataStoreConnection)} methods shall not close
the stream or
+     * database connection returned by this method. In addition, those {@code canOpen(DataStoreConnection)}
      * 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.

Added: 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=1489846&view=auto
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
(added)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
[UTF-8] Wed Jun  5 13:10:29 2013
@@ -0,0 +1,86 @@
+/*
+ * 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.storage;
+
+
+/**
+ * Creates {@link DataStore} instances for a specific format from a given {@link DataStoreConnection}
input.
+ * There is typically a different {@code DataStoreProvider} instance for each format provided
by a library.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3
+ * @version 0.3
+ * @module
+ */
+public abstract class DataStoreProvider {
+    /**
+     * Creates a new provider.
+     */
+    protected DataStoreProvider() {
+    }
+
+    /**
+     * Returns {@code TRUE} if the given storage appears to be supported by the {@code DataStore}.
+     * Returning {@code TRUE} 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 DataStoreConnection#getStorage() storage object} or contents.
+     *
+     * <p>Implementations will typically check the first bytes of the stream for a
"magic number"
+     * associated with the format, as in the following example:</p>
+     *
+     * {@preformat java
+     *     final ByteBuffer buffer = storage.getStorageAs(ByteBuffer.class);
+     *     if (buffer == null) {
+     *         // If DataStoreConnection can not provide a ByteBuffer, then the storage is
probably
+     *         // not a File, URL, URI, InputStream neither a ReadableChannel. In this example,
our
+     *         // provider can not handle such unknown source.
+     *         return Boolean.FALSE;
+     *     }
+     *     if (buffer.remaining() < Integer.SIZE / Byte.SIZE) {
+     *         // If the buffer does not contain enough bytes for the 'int' 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 'null' means "don't know".
+     *         return null;
+     *     }
+     *     // Use ByteBuffer.getInt(int) instead than ByteBuffer.getInt() in order to keep
buffer position
+     *     // unchanged after this method call.
+     *     return buffer.getInt(buffer.position()) == MAGIC_NUMBER;
+     * }
+     *
+     * 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 {@link Boolean#TRUE} if the given storage seems to be usable by the {@code
DataStore} instances
+     *         create by this provider, {@link Boolean#FALSE} if the {@code DataStore} will
not be able to use
+     *         the given storage, or {@code null} if this method does not have enough information.
+     * @throws DataStoreException if an I/O or SQL error occurred. The error shall be unrelated
to the logical
+     *         structure of the storage.
+     */
+    public abstract Boolean canOpen(DataStoreConnection storage) throws DataStoreException;
+
+    /**
+     * Returns a data store implementation associated with this provider.
+     *
+     * @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.
+     */
+    public abstract DataStore open(DataStoreConnection storage) throws DataStoreException;
+}

Propchange: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8



Mime
View raw message