sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1515763 [2/2] - in /sis/branches/JDK6: ./ application/sis-console/src/main/java/org/apache/sis/console/ application/sis-console/src/main/resources/org/apache/sis/console/ core/sis-utility/src/main/java/org/apache/sis/internal/util/ core/si...
Date Tue, 20 Aug 2013 10:35:43 GMT
Modified: sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java?rev=1515763&r1=1515762&r2=1515763&view=diff
==============================================================================
--- sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java
[UTF-8] (original)
+++ sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java
[UTF-8] Tue Aug 20 10:35:42 2013
@@ -16,65 +16,87 @@
  */
 package org.apache.sis.storage;
 
+import java.io.Serializable;
+import java.io.ObjectStreamException;
+import org.apache.sis.util.Debug;
+import org.apache.sis.util.Version;
+import org.apache.sis.internal.util.Utilities;
+
+// Related to JDK7
+import org.apache.sis.internal.jdk7.Objects;
+
 
 /**
  * Tells whether a storage (file, database) 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>{@code UNSUPPORTED_*} indicate that the storage can not be opened. The actual
enumeration value gives
- *       the reason (e.g. unsupported format or {@linkplain #UNSUPPORTED_VERSION unsupported
version}).</li>
- *   <li>{@link #INSUFFICIENT_BYTES} or {@link #UNDETERMINED} indicate 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>
- * </ul>
+ * {@code ProbeResult} may also provide additional information, like file MIME type and the
+ * format version.
  *
+ * {@section Usage}
  * 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
+ * providers and invoke the {@link DataStoreProvider#probeContent(StorageConnector)} method
for each of them.
+ * The {@code ProbeResult} value returned by {@code probeContent(…)} tells to SIS whether
a particular
  * {@code DataStoreProvider} instance has reasonable chances to be able to handle the given
storage.
  *
+ * <p>Whether a storage appears to be supported or not is given by the {@link #isSupported()}
property.
+ * Other properties like {@link #getVersion()} are sometime available for both supported
and unsupported storages.
+ * For example a file may be encoded in a known format, but may be using an unsupported version
of that format.</p>
+ *
+ * {@section Special values}
+ * In addition to the supported/unsupported information, {@code ProbeResult} defines two
constants having
+ * a special meaning: {@link #INSUFFICIENT_BYTES} and {@link #UNDETERMINED}, which indicate
that the provider does
+ * not have enough information for telling whether the storage can be opened.
+ * In such cases, SIS will revisit those providers only if no better suited provider is found.
+ *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
  * @version 0.4
  * @module
  *
- * @see DataStoreProvider#canOpen(StorageConnector)
+ * @see DataStoreProvider#probeContent(StorageConnector)
  */
-public enum ProbeResult {
+public class ProbeResult implements Serializable {
     /**
-     * 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.
+     * For cross-version compatibility.
      */
-    SUPPORTED,
+    private static final long serialVersionUID = -4977853847503500550L;
+
+    /**
+     * The {@code DataStoreProvider} recognizes the given storage, but has no additional
information.
+     * The {@link #isSupported()} method returns {@code true}, but the {@linkplain #getMimeType()
MIME type}
+     * and {@linkplain #getVersion() version} properties are {@code null}.
+     *
+     * <p>{@link DataStoreProvider#probeContent(StorageConnector)} implementations
should consider returning a
+     * {@linkplain #ProbeResult(boolean, String, Version) new instance} instead than this
constant
+     * if they can provide the file MIME type or the format version number.</p>
+     */
+    public static final ProbeResult SUPPORTED = new Constant(true, "SUPPORTED");
 
     /**
      * The {@code DataStoreProvider} does not recognize the given storage object, file format
or database schema.
-     * Examples:
+     * No other information is available: the {@link #isSupported()} method returns {@code
false}, and the
+     * {@linkplain #getMimeType() MIME type} and {@linkplain #getVersion() version} properties
are {@code null}.
      *
+     * <p>Examples:</p>
      * <ul>
      *   <li>The storage is a file while the provider expected a database connection
(or conversely).</li>
      *   <li>The file does not contains the expected magic number.</li>
      *   <li>The database schema does not contain the expected tables.</li>
      * </ul>
-     */
-    UNSUPPORTED_STORAGE,
-
-    /**
-     * The {@code DataStoreProvider} recognizes the given storage, but the data are structured
+     *
+     * {@link DataStoreProvider#probeContent(StorageConnector)} implementations should consider
returning a
+     * {@linkplain #ProbeResult(boolean, String, Version) new instance} instead than this
constant
+     * if 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.
      */
-    UNSUPPORTED_VERSION,
+    public static final ProbeResult UNSUPPORTED_STORAGE = new Constant(false, "UNSUPPORTED_STORAGE");
 
     /**
      * The open capability can not be determined because the {@link ByteBuffer} contains
an insufficient
-     * amount of bytes. This value may be returned by {@link DataStoreProvider#canOpen(StorageConnector)}
-     * implementations similar to the following:
+     * amount of bytes. This value can be returned by {@link DataStoreProvider#probeContent(StorageConnector)}
+     * implementations as below:
      *
      * {@preformat java
-     *     public ProbeResult canOpen(StorageConnector storage) throws DataStoreException
{
+     *     public ProbeResult probeContent(StorageConnector storage) throws DataStoreException
{
      *         final ByteBuffer buffer = storage.getStorageAs(ByteBuffer.class);
      *         if (buffer == null) {
      *             return ProbeResult.UNSUPPORTED_STORAGE;
@@ -86,21 +108,215 @@ public enum ProbeResult {
      *     }
      * }
      *
-     * When some {@code DataStoreProvider} return this value, SIS will first continue the
search for a provider that
-     * can answer the {@code canOpen(…)} question using only the available bytes. Only
if no provider is found,
-     * then SIS will fetch more bytes and try again the providers that returned {@code INSUFFICIENT_BYTES}.
+     * When searching for a provider capable to read a given file,
+     * if at least one {@code DataStoreProvider} returns {@code INSUFFICIENT_BYTES}, then:
+     *
+     * <ol>
+     *   <li>SIS will continue to search for an other provider for which {@code probeContent(…)}
+     *       declares to support the storage, using only the available bytes.</li>
+     *   <li>Only if no such provider can be found, then SIS will fetch more bytes
and query again
+     *       the providers that returned {@code INSUFFICIENT_BYTES} in the previous iteration.</li>
+     * </ol>
+     *
      * SIS tries to work with available bytes before to ask more in order to reduce latencies
on network connections.
      */
-    INSUFFICIENT_BYTES,
+    public static final ProbeResult INSUFFICIENT_BYTES = new Constant(false, "INSUFFICIENT_BYTES");
 
     /**
      * The open capability can not be determined.
      * This value may be returned by {@code DataStore} implementations that could potentially
open anything,
-     * as for example of the RAW image format.
+     * for example the RAW image format.
      *
-     * <p><strong>This is a last resort value!</strong> {@code canOpen(…)}
implementations are strongly encouraged
+     * <p><strong>This is a last resort value!</strong> {@code probeContent(…)}
implementations are strongly encouraged
      * to return a more accurate enumeration value for allowing {@link DataStores#open(Object)}
to perform a better
-     * choice. Generally, this value should be used only by the RAW image format.</p>
+     * choice. Generally, this value should be returned only by the RAW image format.</p>
+     */
+    public static final ProbeResult UNDETERMINED = new Constant(false, "UNDETERMINED");
+
+    /**
+     * {@code true} if the storage is supported by the {@link DataStoreProvider}.
+     *
+     * @see #isSupported()
+     */
+    private final boolean isSupported;
+
+    /**
+     * The storage MIME type, or {@code null} if unknown or not applicable.
+     *
+     * @see #getMimeType()
+     */
+    private final String mimeType;
+
+    /**
+     * The version of file format or database schema used by the storage, or {@code null}
if unknown or not applicable.
+     *
+     * @see #getVersion()
+     */
+    private final Version version;
+
+    /**
+     * Creates a new {@code ProbeResult} with the given support status, MIME type and version
number.
+     *
+     * @param isSupported {@code true} if the storage is supported by the {@link DataStoreProvider}.
+     * @param mimeType    The storage MIME type, or {@code null} if unknown or not applicable.
+     * @param version     The version of file format or database schema used by the storage,
+     *                    or {@code null} if unknown or not applicable.
+     */
+    public ProbeResult(final boolean isSupported, final String mimeType, final Version version)
{
+        this.isSupported = isSupported;
+        this.mimeType    = mimeType;
+        this.version     = version;
+    }
+
+    /**
+     * Returns {@code true} if the storage is supported by the {@code DataStoreProvider}.
+     * {@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.
+     *
+     * @return {@code true} if the storage is supported by the {@link DataStoreProvider}.
+     */
+    public boolean isSupported() {
+        return isSupported;
+    }
+
+    /**
+     * Returns the MIME type of the storage file format, or {@code null} if unknown or not
applicable.
+     * The {@link DataStoreProvider} may (at implementation choice) inspect the storage content
for
+     * determining a more accurate MIME type.
+     *
+     * {@section XML types}
+     * A generic MIME type for XML documents is {@code "application/xml"}.
+     * However many other MIME types exist for XML documents compliant to some particular
shema.
+     * Those types can be determined by inspecting the namespace of XML root element.
+     * The following table gives some example:
+     *
+     * <table class="sis">
+     *   <tr><th>MIME type</th>                                       
            <th>Description</th>                                 <th>Namespace</th></tr>
+     *   <tr><td>{@code "application/gml+xml"}</td>                   
            <td>Official mime type for OGC GML</td>              <td>{@value
org.apache.sis.XML.Namespaces#GML}</td></tr>
+     *   <tr><td>{@code "application/vnd.eu.europa.ec.inspire.resource+xml"}</td>
 <td>Official mime type for INSPIRE Resources</td>    <td></td></tr>
+     *   <tr><td>{@code "application/vnd.iso.19139+xml"}</td>         
            <td>Unofficial mime type for ISO 19139 metadata</td> <td>{@value
org.apache.sis.XML.Namespaces#GMD}</td></tr>
+     *   <tr><td>{@code "application/vnd.ogc.wms_xml"}</td>           
            <td>Unofficial mime type for OGC WMS</td>            <td></td></tr>
+     *   <tr><td>{@code "application/vnd.ogc.wfs_xml"}</td>           
            <td>Unofficial mime type for OGC WFS </td>           <td></td></tr>
+     *   <tr><td>{@code "application/vnd.ogc.csw_xml"}</td>           
            <td>Unofficial mime type for OGC CSW</td>            <td>{@value
org.apache.sis.XML.Namespaces#CSW}</td></tr>
+     *   <tr><td>{@code "application/vnd.google-earth.kml+xml"}</td>  
            <td></td><td></td></tr>
+     *   <tr><td>{@code "application/rdf+xml"}</td>                   
            <td></td><td></td></tr>
+     *   <tr><td>{@code "application/soap+xml"}</td>                  
            <td></td><td></td></tr>
+     * </table>
+     *
+     * @return The storage MIME type, or {@code null} if unknown or not applicable.
+     */
+    public String getMimeType() {
+        return mimeType;
+    }
+
+    /**
+     * Returns the version of file format or database schema used by the storage,
+     * or {@code null} if unknown or not applicable.
+     *
+     * @return The version of file format or database schema used by the storage,
+     *         or {@code null} if unknown or not applicable.
+     */
+    public Version getVersion() {
+        return version;
+    }
+
+    /**
+     * Returns a hash code value for this instance.
+     */
+    @Override
+    public int hashCode() {
+        return Objects.hash(isSupported, mimeType, version) ^ (int) serialVersionUID;
+    }
+
+    /**
+     * Compares this {@code ProbeResult} with the given object for equality.
+     * Two {@code ProbeResult}s are equal if they are instances of the same class
+     * and all their properties are equal.
+     *
+     * @param  object The object to compare with this {@code ProbeResult}.
+     * @return {@code true} if the two objects are equal.
      */
-    UNDETERMINED
+    @Override
+    public boolean equals(final Object object) {
+        if (object != null && object.getClass() == getClass()) {
+            final ProbeResult other = (ProbeResult) object;
+            return isSupported == other.isSupported &&
+                    Objects.equals(mimeType, other.mimeType) &&
+                    Objects.equals(version,  other.version);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a string representation of this {@code ProbeResult} for debugging purpose.
+     */
+    @Debug
+    @Override
+    public String toString() {
+        return Utilities.toString(getClass(), "isSupported", isSupported, "mimeType", mimeType,
"version", version);
+    }
+
+    /**
+     * Implementation of static constants defined in {@link ProbeResult}.
+     * We need a special implementation class in order to resolve deserialized instances
to their unique instance.
+     */
+    private static final class Constant extends ProbeResult {
+        /**
+         * For cross-version compatibility.
+         */
+        private static final long serialVersionUID = -5239064423134309133L;
+
+        /**
+         * The name of the public static field constant.
+         * Each name shall be unique.
+         */
+        private final String name;
+
+        /**
+         * Creates a new constant for a public static field of the given name.
+         */
+        Constant(final boolean isSupported, final String name) {
+            super(isSupported, null, null);
+            this.name = name;
+        }
+
+        /**
+         * Invoked on deserialization for fetching the unique instance, if possible.
+         * If we fail to resolve (which may happen if the instance has been serialized
+         * by a more recent SIS version), returns the instance unchanged. It should be
+         * okay if all comparisons are performed by the {@code equals} method instead
+         * than the {@code ==} operator.
+         */
+        Object readResolve() throws ObjectStreamException {
+            try {
+                return ProbeResult.class.getField(name).get(null);
+            } catch (Exception e) { // ReflectiveOperationException on the JDK7 branch.
+                return this; // See javadoc
+            }
+        }
+
+        /**
+         * Compares the name, which is okay since each name are unique.
+         */
+        @Override
+        public boolean equals(final Object object) {
+            return (object instanceof Constant) && name.equals(((Constant) object).name);
+        }
+
+        /**
+         * Returns a hash code derived from the name, which is okay since each name are unique.
+         */
+        @Override
+        public int hashCode() {
+            return name.hashCode() ^ (int) serialVersionUID;
+        }
+
+        /**
+         * Returns the constant name for debugging purpose.
+         */
+        @Override
+        public String toString() {
+            return "ProbeResult[" + name + ']';
+        }
+    }
 }

Modified: sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java?rev=1515763&r1=1515762&r2=1515763&view=diff
==============================================================================
--- sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
[UTF-8] (original)
+++ sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
[UTF-8] Tue Aug 20 10:35:42 2013
@@ -353,8 +353,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#canOpen(StorageConnector)} methods shall not close the stream
or
-     * database connection returned by this method. In addition, those {@code canOpen(StorageConnector)}
+     * {@link DataStoreProvider#probeContent(StorageConnector)} methods shall not close the
stream or
+     * database connection returned by this method. In addition, those {@code probeContent(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.
@@ -536,7 +536,7 @@ public class StorageConnector implements
      * channel or stream, we have reached the end of stream, or the buffer is full.
      *
      * <p>This method is invoked when the amount of bytes in the buffer appears to
be insufficient
-     * for {@link DataStoreProvider#canOpen(StorageConnector)} purpose.</p>
+     * for {@link DataStoreProvider#probeContent(StorageConnector)} purpose.</p>
      *
      * @return {@code true} on success.
      * @throws DataStoreException If an error occurred while reading more bytes.
@@ -623,6 +623,17 @@ public class StorageConnector implements
                 final Charset encoding = getOption(OptionKey.ENCODING);
                 final Reader c = (encoding != null) ? new InputStreamReader(input, encoding)
                                                     : new InputStreamReader(input);
+                /*
+                 * Current implementation does not wrap the above Reader in a BufferedReader
because:
+                 *
+                 * 1) InputStreamReader already uses a buffer internally.
+                 * 2) InputStreamReader does not support mark/reset, which is a desired limitation
for now.
+                 *    This is because reseting the Reader would not reset the underlying
InputStream, which
+                 *    would cause other DataStoreProvider.probeContent(…) methods to fail
if they try to use
+                 *    the InputStream. For now we let the InputStreamReader.mark() to throws
an IOException,
+                 *    but we may need to provide our own subclass of BufferedReader in a
future SIS version
+                 *    if mark/reset support is needed here.
+                 */
                 addViewToClose(c, input);
                 return c;
             }

Modified: sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreProviderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreProviderTest.java?rev=1515763&r1=1515762&r2=1515763&view=diff
==============================================================================
--- sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreProviderTest.java
[UTF-8] (original)
+++ sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreProviderTest.java
[UTF-8] Tue Aug 20 10:35:42 2013
@@ -36,15 +36,17 @@ import static org.junit.Assert.*;
  */
 public final strictfp class XMLStoreProviderTest extends TestCase {
     /**
-     * Tests {@link XMLStoreProvider#canOpen(StorageConnector)} method from a {@link Reader}
object.
+     * Tests {@link XMLStoreProvider#probeContent(StorageConnector)} method from a {@link
Reader} object.
      *
      * @throws DataStoreException Should never happen.
      */
     @Test
-    public void testCanOpenFromReader() throws DataStoreException {
+    public void testProbeContentFromReader() throws DataStoreException {
         final XMLStoreProvider p = new XMLStoreProvider();
         final StorageConnector c = new StorageConnector(new StringReader(XMLStoreTest.XML));
-        assertEquals(ProbeResult.SUPPORTED, p.canOpen(c));
+        final ProbeResult      r = p.probeContent(c);
         c.closeAllExcept(null);
+        assertTrue  ("isSupported()", r.isSupported());
+        assertEquals("getMimeType()", "application/vnd.iso.19139+xml", r.getMimeType());
     }
 }

Modified: sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreTest.java?rev=1515763&r1=1515762&r2=1515763&view=diff
==============================================================================
--- sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreTest.java
[UTF-8] (original)
+++ sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreTest.java
[UTF-8] Tue Aug 20 10:35:42 2013
@@ -46,7 +46,7 @@ public final strictfp class XMLStoreTest
     /**
      * The metadata to unmarshal.
      */
-    static final String XML =
+    public static final String XML =
             "<?xml version=\"1.0\" standalone=\"yes\"?>\n" +
             "<gmd:MD_Metadata\n" +
             "  xmlns:gmd = \"" + Namespaces.GMD + "\"\n"  +

Modified: sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java?rev=1515763&r1=1515762&r2=1515763&view=diff
==============================================================================
--- sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
[UTF-8] (original)
+++ sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
[UTF-8] Tue Aug 20 10:35:42 2013
@@ -33,9 +33,12 @@ import org.junit.BeforeClass;
     org.apache.sis.internal.storage.IOUtilitiesTest.class,
     org.apache.sis.internal.storage.ChannelDataInputTest.class,
     org.apache.sis.internal.storage.ChannelImageInputStreamTest.class,
+    org.apache.sis.storage.ProbeResultTest.class,
     org.apache.sis.storage.StorageConnectorTest.class,
+    org.apache.sis.internal.storage.xml.MimeTypeDetectorTest.class,
     org.apache.sis.internal.storage.xml.XMLStoreProviderTest.class,
     org.apache.sis.internal.storage.xml.XMLStoreTest.class,
+    org.apache.sis.storage.DataStoresTest.class,
     org.apache.sis.index.GeoHashCoderTest.class
 })
 public final strictfp class StorageTestSuite extends TestSuite {



Mime
View raw message