sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1807628 [2/5] - in /sis/branches/JDK7: ./ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ core/sis-metadata/src/main/java/org/apache/sis/metadata/ core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/ core/sis...
Date Thu, 07 Sep 2017 16:41:03 GMT
Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -371,7 +371,7 @@ public final class Units extends Static
      * <table class="compact" summary="Related units" style="margin-left:30px; line-height:1.25">
      *   <tr><td>SI angle units:</td>   <td style="word-spacing:1em">{@link #MICRORADIAN}, <u><b>{@code RADIAN}</b></u>.</td></tr>
      *   <tr><td>In other systems:</td> <td style="word-spacing:1em">{@link #DEGREE}, {@link #ARC_MINUTE}, {@link #ARC_SECOND}, {@link #GRAD}.</td></tr>
-     *   <tr><td>Derived units:</td>    <td style="word-spacing:1em">{@link #STERADIAN}.</td></tr>
+     *   <tr><td>Derived units:</td>    <td style="word-spacing:1em">{@link #STERADIAN}, {@link #RADIANS_PER_SECOND}.</td></tr>
      * </table></div>
      *
      * @since 0.8
@@ -582,6 +582,19 @@ public final class Units extends Static
     public static final Unit<Frequency> HERTZ;
 
     /**
+     * The unit for angular velocity (rad/s).
+     * The identifier is EPSG:1035.
+     *
+     * <div class="note"><p class="simpleTagLabel" style="margin-bottom:0">Related units:</p>
+     * <table class="compact" summary="Related units" style="margin-left:30px; line-height:1.25">
+     *   <tr><td>Components:</td> <td style="word-spacing:0.5em">{@link #RADIAN} ∕ {@link #SECOND}</td></tr>
+     * </table></div>
+     *
+     * @since 0.8
+     */
+    public static final Unit<AngularVelocity> RADIANS_PER_SECOND;
+
+    /**
      * The SI derived unit for speed (m/s).
      * The unlocalized name is “metres per second” and the identifier is EPSG:1026.
      *
@@ -1020,10 +1033,9 @@ public final class Units extends Static
      * Salinity measured using PSS-78. While this is a dimensionless measurement, the {@code "psu"} symbol
      * is sometime added to PSS-78 measurement. However this is officially discouraged.
      *
-     * <p>If we make this field public in a future SIS version, we should consider introducing a
-     * {@code Salinity} quantity type.</p>
+     * @since 0.8
      */
-    static final Unit<Dimensionless> PSU;
+    public static final Unit<Salinity> PSU;
 
     /**
      * Sigma-level, used in oceanography. This is a way to measure a depth as a fraction of the sea floor depth.
@@ -1069,6 +1081,7 @@ public final class Units extends Static
         final UnitDimension temperature   = new UnitDimension('Θ');
         final UnitDimension amount        = new UnitDimension('N');
         final UnitDimension luminous      = new UnitDimension('J');
+        final UnitDimension frequency     = time.pow(-1);
         final UnitDimension area          = length.pow(2);
         final UnitDimension speed         = length.divide(time);
         final UnitDimension force         = mass.multiply(speed).divide(time);
@@ -1145,11 +1158,19 @@ public final class Units extends Static
         WEEK           = add(s, LinearConverter.scale( 7*24*60*60,      1), "wk",  OTHER,    (short) 0);
         TROPICAL_YEAR  = add(s, LinearConverter.scale(31556925445.0, 1000), "a",   OTHER,    (short) 1029);
         /*
-         * All Unit<Speed>.
-         */
+         * All Unit<Speed>, Unit<AngularVelocity> and Unit<ScaleRateOfChange>.
+         * The 'unityPerSecond' unit is not added to the registry because it is specific to the EPSG database,
+         * has no clear symbol and is easy to confuse with Hertz. We create that unit only for allowing us to
+         * create the "ppm/a" units.
+         */
+        final SystemUnit<ScaleRateOfChange> unityPerSecond;
+        unityPerSecond = new SystemUnit<>(ScaleRateOfChange.class, frequency, null, OTHER, (short) 1036, null);
+        unityPerSecond.related(1);
         mps.related(1);
         METRES_PER_SECOND   = mps;
-        KILOMETRES_PER_HOUR = add(mps, LinearConverter.scale(10, 36), "km∕h", ACCEPTED, (short) 0);
+        KILOMETRES_PER_HOUR = add(mps, LinearConverter.scale(10, 36),     "km∕h",  ACCEPTED, (short) 0);
+        RADIANS_PER_SECOND  = add(AngularVelocity.class, null, frequency, "rad∕s", SI,       (short) 1035);
+        add(unityPerSecond, LinearConverter.scale(1, 31556925445E6),      "ppm∕a", OTHER,    (short) 1030);
         /*
          * All Unit<Pressure>.
          */
@@ -1179,12 +1200,14 @@ public final class Units extends Static
         GRAM         = add(kg, milli, "g", (byte) (ACCEPTED | PREFIXABLE), (short) 0);
         /*
          * Force, energy, electricity, magnetism and other units.
+         * Frequency must be defined after angular velocities.
+         *
          * Note: JDK8 branch uses method references instead than inner classes.
          */
-        HERTZ      = add(Frequency.class, new ScalarFactory<Frequency>() {@Override public Frequency create(double value, Unit<Frequency> unit) {return new Scalar.Frequency(value, unit);}}, time.pow(-1), "Hz", (byte) (SI | PREFIXABLE), (short) 0);
-        NEWTON     = add(Force.class,     new ScalarFactory<Force>    () {@Override public Force     create(double value, Unit<Force>     unit) {return new Scalar.Force    (value, unit);}}, force,        "N",  (byte) (SI | PREFIXABLE), (short) 0);
-        JOULE      = add(Energy.class,    new ScalarFactory<Energy>   () {@Override public Energy    create(double value, Unit<Energy>    unit) {return new Scalar.Energy   (value, unit);}}, energy,       "J",  (byte) (SI | PREFIXABLE), (short) 0);
-        WATT       = add(Power.class,     new ScalarFactory<Power>    () {@Override public Power     create(double value, Unit<Power>     unit) {return new Scalar.Power    (value, unit);}}, power,        "W",  (byte) (SI | PREFIXABLE), (short) 0);
+        HERTZ      = add(Frequency.class, new ScalarFactory<Frequency>() {@Override public Frequency create(double value, Unit<Frequency> unit) {return new Scalar.Frequency(value, unit);}}, frequency, "Hz", (byte) (SI | PREFIXABLE), (short) 0);
+        NEWTON     = add(Force.class,     new ScalarFactory<Force>    () {@Override public Force     create(double value, Unit<Force>     unit) {return new Scalar.Force    (value, unit);}}, force,     "N",  (byte) (SI | PREFIXABLE), (short) 0);
+        JOULE      = add(Energy.class,    new ScalarFactory<Energy>   () {@Override public Energy    create(double value, Unit<Energy>    unit) {return new Scalar.Energy   (value, unit);}}, energy,    "J",  (byte) (SI | PREFIXABLE), (short) 0);
+        WATT       = add(Power.class,     new ScalarFactory<Power>    () {@Override public Power     create(double value, Unit<Power>     unit) {return new Scalar.Power    (value, unit);}}, power,     "W",  (byte) (SI | PREFIXABLE), (short) 0);
         AMPERE     = add(ElectricCurrent.class,     null,                  current,                      "A",   (byte) (SI | PREFIXABLE), (short) 0);
         COULOMB    = add(ElectricCharge.class,      null,                  charge,                       "C",   (byte) (SI | PREFIXABLE), (short) 0);
         VOLT       = add(ElectricPotential.class,   null,                  potential,                    "V",   (byte) (SI | PREFIXABLE), (short) 0);
@@ -1205,7 +1228,7 @@ public final class Units extends Static
          */
         PERCENT = add(one, centi,                                               "%",     OTHER, (short) 0);
         PPM     = add(one, micro,                                               "ppm",   OTHER, (short) 9202);
-        PSU     = add(Dimensionless.class, dimensionlessFactory, dimensionless, "psu",   OTHER, (short) 0);
+        PSU     = add(Salinity.class,      null,                 dimensionless, "psu",   OTHER, (short) 0);
         SIGMA   = add(Dimensionless.class, dimensionlessFactory, dimensionless, "sigma", OTHER, (short) 0);
         PIXEL   = add(Dimensionless.class, dimensionlessFactory, dimensionless, "px",    OTHER, (short) 0);
         UNITY   = UnitRegistry.init(one);  // Must be last in order to take precedence over all other units associated to UnitDimension.NONE.

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -104,19 +104,25 @@ public class DefaultRecord implements Re
      *
      * @since 0.8
      */
+    @SuppressWarnings("SuspiciousSystemArraycopy")
     public DefaultRecord(final Record record) {
         this(record.getRecordType());
-        for (final Map.Entry<MemberName,Integer> entry : definition.memberIndices().entrySet()) {
-            final MemberName name = entry.getKey();
-            final Object value = record.locate(name);
-            if (value != null) {
-                final int index = entry.getValue();
-                final Class<?> valueClass = definition.getValueClass(index);
-                if (valueClass != null && !valueClass.isInstance(value)) {
-                    throw new ClassCastException(Errors.format(Errors.Keys.IllegalPropertyValueClass_3,
-                            name, valueClass, value.getClass()));
+        if (record instanceof DefaultRecord) {
+            final Object source = ((DefaultRecord) record).values;
+            System.arraycopy(source, 0, values, 0, Array.getLength(source));
+        } else {
+            for (final Map.Entry<MemberName,Integer> entry : definition.memberIndices().entrySet()) {
+                final MemberName name = entry.getKey();
+                final Object value = record.locate(name);
+                if (value != null) {
+                    final int index = entry.getValue();
+                    final Class<?> valueClass = definition.getValueClass(index);
+                    if (valueClass != null && !valueClass.isInstance(value)) {
+                        throw new ClassCastException(Errors.format(Errors.Keys.IllegalPropertyValueClass_3,
+                                name, valueClass, value.getClass()));
+                    }
+                    Array.set(values, index, value);
                 }
-                Array.set(values, index, value);
             }
         }
     }

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/NilReason.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/NilReason.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/NilReason.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/NilReason.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -145,7 +145,7 @@ public final class NilReason implements
 
     /**
      * Either the XML value as a {@code String} (including the explanation if the prefix
-     * is "{@code other}", or an {@link URI}.
+     * is "{@code other}", or a {@link URI}.
      */
     private final Object reason;
 

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -112,7 +112,7 @@ public class ReferenceResolver {
      * The default implementation performs the following lookups:
      *
      * <ul>
-     *   <li>If the {@link XLink#getHRef() xlink:href} attribute is an {@linkplain URI#getFragment() URI fragment}
+     *   <li>If the {@link XLink#getHRef() xlink:href} attribute is a {@linkplain URI#getFragment() URI fragment}
      *       of the form {@code "#foo"} and if an object of class {@code type} with the {@code gml:id="foo"} attribute
      *       has previously been seen in the same XML document, then that object is returned.</li>
      *   <li>Otherwise returns {@code null}.</li>

Modified: sis/branches/JDK7/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames.properties?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames.properties [ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames.properties [ISO-8859-1] Thu Sep  7 16:41:02 2017
@@ -45,6 +45,7 @@ psu=practical salinity unit
 pt=point
 px=pixel
 rad=radian
+rad\u2215s=radians per second
 s=second
 S=siemens
 sr=steradian

Modified: sis/branches/JDK7/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_fr.properties?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_fr.properties [ISO-8859-1] Thu Sep  7 16:41:02 2017
@@ -24,6 +24,7 @@ mm=millimètre
 ms=milliseconde
 nm=nanomètre
 ppm=parties par million
+rad\u2215s=radians par seconde
 s=seconde
 sr=stéradian
 unity=unité

Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/UnitFormatTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/UnitFormatTest.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/UnitFormatTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/UnitFormatTest.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -90,6 +90,7 @@ public final strictfp class UnitFormatTe
         verify(declared, "WEEK",                "T",            "wk",    "week",                    Units.WEEK);
         verify(declared, "TROPICAL_YEAR",       "T",            "a",     "year",                    Units.TROPICAL_YEAR);
         verify(declared, "HERTZ",               "∕T",           "Hz",    "hertz",                   Units.HERTZ);
+        verify(declared, "RADIANS_PER_SECOND",  "∕T",           "rad∕s", "radians per second",      Units.RADIANS_PER_SECOND);
         verify(declared, "METRES_PER_SECOND",   "L∕T",          "m∕s",   "metres per second",       Units.METRES_PER_SECOND);
         verify(declared, "KILOMETRES_PER_HOUR", "L∕T",          "km∕h",  "kilometres per hour",     Units.KILOMETRES_PER_HOUR);
         verify(declared, "PASCAL",              "M∕(L⋅T²)",     "Pa",    "pascal",                  Units.PASCAL);

Modified: sis/branches/JDK7/ide-project/NetBeans/build.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/ide-project/NetBeans/build.xml?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/ide-project/NetBeans/build.xml (original)
+++ sis/branches/JDK7/ide-project/NetBeans/build.xml Thu Sep  7 16:41:02 2017
@@ -226,6 +226,9 @@
         <include name="**/*.laa"/>
         <include name="**/*.loa"/>
       </fileset>
+      <fileset dir="${project.root}/storage/sis-storage/src/test/resources">
+        <include name="**/*.txt"/>
+      </fileset>
       <fileset dir="${project.root}/storage/sis-xmlstore/src/test/resources">
         <include name="**/*.gpx"/>
         <include name="**/*.xml"/>

Modified: sis/branches/JDK7/pom.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/pom.xml?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/pom.xml (original)
+++ sis/branches/JDK7/pom.xml Thu Sep  7 16:41:02 2017
@@ -788,7 +788,7 @@ Apache SIS is a free software, Java lang
       <!-- JavaDoc configuration. -->
       <plugin>
         <artifactId>maven-javadoc-plugin</artifactId>
-        <version>2.10.4</version>
+        <version>2.10.4</version> <!-- 3.0.0-M1 is required for JDK9, but contains a regression that prevent javadoc:aggregate to work. -->
         <configuration>
           <source>${maven.compile.source}</source>              <!-- Enables javadoc to handle language constructs present in target JDK. -->
           <encoding>${project.build.sourceEncoding}</encoding>  <!-- Encoding of Java source file. -->

Modified: sis/branches/JDK7/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatStore.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatStore.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatStore.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatStore.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -20,15 +20,17 @@ import java.io.Reader;
 import java.io.BufferedReader;
 import java.io.LineNumberReader;
 import java.io.IOException;
+import java.net.URI;
 import org.opengis.metadata.Metadata;
 import org.opengis.util.FactoryException;
+import org.opengis.parameter.ParameterValueGroup;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreReferencingException;
 import org.apache.sis.storage.UnsupportedStorageException;
 import org.apache.sis.storage.StorageConnector;
+import org.apache.sis.internal.storage.URIDataStore;
 import org.apache.sis.setup.OptionKey;
-import org.apache.sis.storage.Resource;
 import org.apache.sis.util.Debug;
 
 
@@ -72,6 +74,11 @@ public class LandsatStore extends DataSt
     private Reader source;
 
     /**
+     * The {@link LandsatStoreProvider#LOCATION} parameter value, or {@code null} if none.
+     */
+    private final URI location;
+
+    /**
      * The object returned by {@link #getMetadata()}, created when first needed and cached.
      */
     private Metadata metadata;
@@ -87,10 +94,11 @@ public class LandsatStore extends DataSt
      */
     public LandsatStore(final LandsatStoreProvider provider, final StorageConnector connector) throws DataStoreException {
         super(provider, connector);
+        location = connector.getStorageAs(URI.class);
         source = connector.getStorageAs(Reader.class);
         connector.closeAllExcept(source);
         if (source == null) {
-            throw new UnsupportedStorageException(super.getLocale(), "Landsat",
+            throw new UnsupportedStorageException(super.getLocale(), LandsatStoreProvider.NAME,
                     connector.getStorage(), connector.getOption(OptionKey.OPEN_OPTIONS));
         }
     }
@@ -121,15 +129,19 @@ public class LandsatStore extends DataSt
     }
 
     /**
-     * Current implementation does not provide any resource yet.
-     * Future versions may return an aggregate of all raster data in the GeoTIFF files associated with this metadata.
+     * Returns the parameters used to open this Landsat data store.
+     * If non-null, the parameters are described by {@link LandsatStoreProvider#getOpenParameters()}
+     * and contains at least a parameter named {@value LandsatStoreProvider#LOCATION} with a {@link URI} value.
+     * This method may return {@code null} if the storage input can not be described by a URI
+     * (for example a Landsat file reading directly from a {@link java.nio.channels.ReadableByteChannel}).
      *
-     * @return the starting point of all resources in this data store.
-     * @throws DataStoreException if an error occurred while reading the data.
+     * @return parameters used for opening this data store, or {@code null} if not available.
+     *
+     * @since 0.8
      */
     @Override
-    public Resource getRootResource() throws DataStoreException {
-        return null;
+    public ParameterValueGroup getOpenParameters() {
+        return URIDataStore.parameters(provider, location);
     }
 
     /**

Modified: sis/branches/JDK7/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatStoreProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatStoreProvider.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatStoreProvider.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatStoreProvider.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.storage.earthobservation;
 
+import org.opengis.parameter.ParameterDescriptorGroup;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreProvider;
 import org.apache.sis.storage.DataStoreException;
@@ -23,6 +24,7 @@ import org.apache.sis.storage.StorageCon
 import org.apache.sis.storage.ProbeResult;
 import org.apache.sis.internal.storage.Capability;
 import org.apache.sis.internal.storage.Capabilities;
+import org.apache.sis.internal.storage.URIDataStore;
 import org.apache.sis.internal.storage.wkt.FirstKeywordPeek;
 
 
@@ -42,6 +44,16 @@ import org.apache.sis.internal.storage.w
 @Capabilities(Capability.READ)
 public class LandsatStoreProvider extends DataStoreProvider {
     /**
+     * The format name.
+     */
+    static final String NAME = "Landsat";
+
+    /**
+     * The parameter descriptor to be returned by {@link #getOpenParameters()}.
+     */
+    private static final ParameterDescriptorGroup OPEN_DESCRIPTOR = URIDataStore.Provider.descriptor(NAME);
+
+    /**
      * The object to use for verifying if the first keyword is the expected one.
      */
     private static final class Peek extends FirstKeywordPeek {
@@ -132,7 +144,19 @@ public class LandsatStoreProvider extend
      */
     @Override
     public String getShortName() {
-        return "Landsat";
+        return NAME;
+    }
+
+    /**
+     * Returns a description of all parameters accepted by this provider for opening a Landsat file.
+     *
+     * @return description of available parameters for opening a Landsat file.
+     *
+     * @since 0.8
+     */
+    @Override
+    public ParameterDescriptorGroup getOpenParameters() {
+        return OPEN_DESCRIPTOR;
     }
 
     /**

Modified: sis/branches/JDK7/storage/sis-gdal/src/main/c/org_apache_sis_storage_gdal_PJ.c
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-gdal/src/main/c/org_apache_sis_storage_gdal_PJ.c?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-gdal/src/main/c/org_apache_sis_storage_gdal_PJ.c [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-gdal/src/main/c/org_apache_sis_storage_gdal_PJ.c [UTF-8] Thu Sep  7 16:41:02 2017
@@ -106,7 +106,9 @@ JNIEXPORT jstring JNICALL Java_org_apach
     if (pj) {
         const char *desc = pj_get_def(pj, 0);
         if (desc) {
-            jstring str = (*env)->NewStringUTF(env, desc);
+            const char *trim = desc;
+            if (*trim == ' ') trim++;
+            jstring str = (*env)->NewStringUTF(env, trim);
             pj_dalloc((char*) desc);
             return str;
         }
@@ -281,12 +283,14 @@ JNIEXPORT void JNICALL Java_org_apache_s
 JNIEXPORT jstring JNICALL Java_org_apache_sis_storage_gdal_PJ_getLastError
   (JNIEnv *env, jobject object)
 {
-    projPJ pj = getPJ(env, object);
-    if (pj) {
-        int err = *pj_get_errno_ref();
-        if (err) {
-            return (*env)->NewStringUTF(env, pj_strerrno(err));
-        }
+    /*
+     * For now we ignore the object reference, but a future version may use it if
+     * we make this method thread-safe with the use of a Proj.4 context parameter.
+     * Note that this method needs to work even if getPJ(env, object) returns NULL.
+     */
+    int err = *pj_get_errno_ref();
+    if (err) {
+        return (*env)->NewStringUTF(env, pj_strerrno(err));
     }
     return NULL;
 }

Modified: sis/branches/JDK7/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/PJ.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/PJ.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/PJ.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/PJ.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -27,12 +27,10 @@ import org.opengis.metadata.citation.Cit
 import org.opengis.referencing.datum.Ellipsoid;
 import org.opengis.referencing.datum.GeodeticDatum;
 import org.opengis.referencing.datum.PrimeMeridian;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.metadata.iso.citation.Citations;
-import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.internal.system.OS;
 
@@ -81,8 +79,8 @@ final class PJ implements Identifier, Se
         Objects.requireNonNull(definition);
         ptr = allocatePJ(definition);
         if (ptr == 0) {
-            throw new InvalidGeodeticParameterException(Errors.format(Errors.Keys.UnparsableStringForClass_2,
-                    CoordinateReferenceSystem.class, definition));
+            // Note: our getLastError() implementation is safe even if pts == 0.
+            throw new InvalidGeodeticParameterException(getLastError());
         }
     }
 
@@ -286,6 +284,7 @@ final class PJ implements Identifier, Se
      * @return the last error that occurred, or {@code null}.
      *
      * @todo this method is not thread-safe. Proj.4 provides a better alternative using a context parameter.
+     *       Note that this method needs to be safe even if {@link #ptr} is 0.
      */
     native String getLastError();
 

Modified: sis/branches/JDK7/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -166,22 +166,13 @@ public final class Proj4 extends Static
          * Append the map projection parameters. Those parameters may include axis lengths (a and b),
          * but not necessarily. If axis lengths are specified, then we will ignore the Ellipsoid instance
          * associated to the CRS.
-         *
-         * The "+over" option is for disabling the default wrapping of output longitudes in the -180 to 180 range.
-         * We do that for having the same behavior between Proj.4 and Apache SIS. No wrapping reduce discontinuity
-         * problems with geometries that cross the anti-meridian.
-         *
-         * The "+no_defs" option is for ensuring that no defaults are read from "/usr/share/proj/proj_def.dat" file.
-         * That file contains default values for various map projections, for example "+lat_1=29.5" and "+lat_2=45.5"
-         * for the "aea" projection. Those defaults are assuming that users want Conterminous U.S. map.
-         * This may cause surprising behavior for users outside USA.
          */
         final StringBuilder definition = new StringBuilder(100);
         definition.append(Proj4Factory.PROJ_PARAM).append(method);
         boolean hasSemiMajor = false;
         boolean hasSemiMinor = false;
         if (parameters != null) {
-            definition.append(" +over +no_defs");                                       // See above comment
+            definition.append(Proj4Factory.STANDARD_OPTIONS);
             for (final GeneralParameterValue parameter : parameters.values()) {
                 if (parameter instanceof ParameterValue<?>) {
                     final ParameterValue<?> pv = (ParameterValue<?>) parameter;
@@ -308,7 +299,7 @@ public final class Proj4 extends Static
      * Creates a new CRS from the given {@literal Proj.4} definition string.
      * Some examples of definition strings are:
      * <ul>
-     *   <li>{@code "+init=epsg:3395"} (see warning below)</li>
+     *   <li>{@code "+init=epsg:3395 +over"} (see warning below)</li>
      *   <li>{@code "+proj=latlong +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"}</li>
      *   <li>{@code "+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +ellps=WGS84 +towgs84=0,0,0"}</li>
      * </ul>

Modified: sis/branches/JDK7/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4Factory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4Factory.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4Factory.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4Factory.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -99,6 +99,20 @@ public class Proj4Factory extends Geodet
     static final String PROJ_PARAM = '+' + Proj4Parser.PROJ + '=';
 
     /**
+     * Options to be added in any {@literal Proj.4} definition strings.
+     * <ul>
+     *   <li>The {@code "+over"} option is for disabling the default wrapping of output longitudes in the -180 to 180 range.
+     *     We do that for having the same behavior between Proj.4 and Apache SIS. No wrapping reduce discontinuity problems
+     *     with geometries that cross the anti-meridian.</li>
+     *   <li>The {@code "+no_defs"} option is for ensuring that no defaults are read from {@code "/usr/share/proj/proj_def.dat"} file.
+     *     That file contains default values for various map projections, for example {@code "+lat_1=29.5"} and {@code "+lat_2=45.5"}
+     *     for the {@code "aea"} projection. Those defaults are assuming that users want Conterminous U.S. map.
+     *     This may cause surprising behavior for users outside USA.</li>
+     * </ul>
+     */
+    static String STANDARD_OPTIONS = " +over +no_defs";
+
+    /**
      * The {@literal Proj.4} parameter used for declaration of axis order.  Proj.4 expects the axis parameter
      * to be exactly 3 characters long, but Apache SIS accepts 2 characters as well. We relax the Proj.4 rule
      * because we use the number of characters for determining the number of dimensions.
@@ -431,7 +445,7 @@ public class Proj4Factory extends Geodet
      */
     public MathTransform createParameterizedTransform(final ParameterValueGroup parameters) throws FactoryException {
         final String proj = name(parameters.getDescriptor(), Errors.Keys.UnsupportedOperation_1);
-        final StringBuilder buffer = new StringBuilder(100).append(PROJ_PARAM).append(proj);
+        final StringBuilder buffer = new StringBuilder(100).append(PROJ_PARAM).append(proj).append(STANDARD_OPTIONS);
         for (final GeneralParameterValue p : parameters.values()) {
             /*
              * Unconditionally ask the parameter name in order to throw an exception

Modified: sis/branches/JDK7/storage/sis-gdal/src/main/resources/native/darwin/libproj-binding.so
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-gdal/src/main/resources/native/darwin/libproj-binding.so?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
Binary files - no diff available.

Modified: sis/branches/JDK7/storage/sis-gdal/src/main/resources/native/linux/libproj-binding.so
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-gdal/src/main/resources/native/linux/libproj-binding.so?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
Binary files - no diff available.

Modified: sis/branches/JDK7/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/PJTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/PJTest.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/PJTest.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/PJTest.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -60,7 +60,7 @@ public final strictfp class PJTest exten
      * Ensures that the given object is the WGS84 definition.
      */
     private static void assertIsWGS84(final PJ pj) {
-        assertEquals("+proj=latlong +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0", pj.getCode().trim());
+        assertEquals("+proj=latlong +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0", pj.getCode());
         assertEquals("Proj4",            pj.getCodeSpace());
         assertSame  (Citations.PROJ4,    pj.getAuthority());
         assertTrue  (Character.isDigit(  pj.getVersion().codePointAt(0)));

Modified: sis/branches/JDK7/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/TransformTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/TransformTest.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/TransformTest.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/TransformTest.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -57,7 +57,7 @@ public class TransformTest extends Param
                     return super.getDefaultParameters(method);
                 } catch (NoSuchIdentifierException e) {
                     FAILURES.add(method);
-                    throw e;
+                    throw e;                            // Instructs ParameterizedTransformTest to skip the test.
                 }
             }
         });
@@ -82,7 +82,7 @@ public class TransformTest extends Param
     @AfterClass
     public static void verifyFailureList() {
         /*
-         * The list of failires is empty if verifyNativeLibraryAvailability() failed,
+         * The list of failures is empty if verifyNativeLibraryAvailability() failed,
          * in which case no test have been run.
          */
         if (!FAILURES.isEmpty()) {

Modified: sis/branches/JDK7/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -18,6 +18,7 @@ package org.apache.sis.storage.geotiff;
 
 import java.util.Locale;
 import java.io.IOException;
+import java.net.URI;
 import java.nio.charset.Charset;
 import java.util.logging.LogRecord;
 import java.nio.charset.StandardCharsets;
@@ -25,6 +26,7 @@ import java.nio.file.StandardOpenOption;
 import org.opengis.util.FactoryException;
 import org.opengis.metadata.Metadata;
 import org.opengis.metadata.maintenance.ScopeCode;
+import org.opengis.parameter.ParameterValueGroup;
 import org.apache.sis.setup.OptionKey;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.StorageConnector;
@@ -33,10 +35,10 @@ import org.apache.sis.storage.DataStoreC
 import org.apache.sis.storage.UnsupportedStorageException;
 import org.apache.sis.internal.storage.io.ChannelDataInput;
 import org.apache.sis.internal.storage.MetadataBuilder;
+import org.apache.sis.internal.storage.URIDataStore;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.metadata.sql.MetadataStoreException;
 import org.apache.sis.storage.DataStoreClosedException;
-import org.apache.sis.storage.Resource;
 import org.apache.sis.util.resources.Errors;
 
 
@@ -63,6 +65,11 @@ public class GeoTiffStore extends DataSt
     private Reader reader;
 
     /**
+     * The {@link GeoTiffStoreProvider#LOCATION} parameter value, or {@code null} if none.
+     */
+    private final URI location;
+
+    /**
      * The metadata, or {@code null} if not yet created.
      *
      * @see #getMetadata()
@@ -84,9 +91,10 @@ public class GeoTiffStore extends DataSt
         this.encoding = (encoding != null) ? encoding : StandardCharsets.US_ASCII;
         final ChannelDataInput input = connector.getStorageAs(ChannelDataInput.class);
         if (input == null) {
-            throw new UnsupportedStorageException(super.getLocale(), "TIFF",
+            throw new UnsupportedStorageException(super.getLocale(), Constants.GEOTIFF,
                     connector.getStorage(), connector.getOption(OptionKey.OPEN_OPTIONS));
         }
+        location = connector.getStorageAs(URI.class);
         connector.closeAllExcept(input);
         try {
             reader = new Reader(this, input);
@@ -126,22 +134,26 @@ public class GeoTiffStore extends DataSt
             } catch (IOException e) {
                 throw new DataStoreException(errors().getString(Errors.Keys.CanNotRead_1, reader.input.filename), e);
             } catch (FactoryException | ArithmeticException e) {
-                throw new DataStoreContentException(getLocale(), "TIFF", reader.input.filename, null).initCause(e);
+                throw new DataStoreContentException(getLocale(), Constants.GEOTIFF, reader.input.filename, null).initCause(e);
             }
         }
         return metadata;
     }
 
     /**
-     * Current implementation does not provide any resource yet.
-     * A future version will return the raster data in a coverage resource.
+     * Returns the parameters used to open this GeoTIFF data store.
+     * If non-null, the parameters are described by {@link GeoTiffStoreProvider#getOpenParameters()}
+     * and contains at least a parameter named {@value GeoTiffStoreProvider#LOCATION} with a {@link URI} value.
+     * This method may return {@code null} if the storage input can not be described by a URI
+     * (for example a GeoTIFF file reading directly from a {@link java.nio.channels.ReadableByteChannel}).
      *
-     * @return the starting point of all resources in this data store.
-     * @throws DataStoreException if an error occurred while reading the data.
+     * @return parameters used for opening this data store, or {@code null} if not available.
+     *
+     * @since 0.8
      */
     @Override
-    public Resource getRootResource() throws DataStoreException {
-        return null;
+    public ParameterValueGroup getOpenParameters() {
+        return URIDataStore.parameters(provider, location);
     }
 
     /**

Modified: sis/branches/JDK7/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStoreProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStoreProvider.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStoreProvider.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStoreProvider.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -18,6 +18,7 @@ package org.apache.sis.storage.geotiff;
 
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import org.opengis.parameter.ParameterDescriptorGroup;
 import org.apache.sis.util.Version;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
@@ -26,6 +27,7 @@ import org.apache.sis.storage.ProbeResul
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.internal.storage.Capabilities;
 import org.apache.sis.internal.storage.Capability;
+import org.apache.sis.internal.storage.URIDataStore;
 import org.apache.sis.internal.util.Constants;
 
 
@@ -58,6 +60,11 @@ public class GeoTiffStoreProvider extend
     private static final Version VERSION = new Version("6.0");
 
     /**
+     * The parameter descriptor to be returned by {@link #getOpenParameters()}.
+     */
+    private static final ParameterDescriptorGroup OPEN_DESCRIPTOR = URIDataStore.Provider.descriptor(Constants.GEOTIFF);
+
+    /**
      * Creates a new provider.
      */
     public GeoTiffStoreProvider() {
@@ -74,6 +81,18 @@ public class GeoTiffStoreProvider extend
     }
 
     /**
+     * Returns a description of all parameters accepted by this provider for opening a GeoTIFF file.
+     *
+     * @return description of available parameters for opening a GeoTIFF file.
+     *
+     * @since 0.8
+     */
+    @Override
+    public ParameterDescriptorGroup getOpenParameters() {
+        return OPEN_DESCRIPTOR;
+    }
+
+    /**
      * Returns {@link ProbeResult#SUPPORTED} if the given storage appears to be supported by {@link GeoTiffStore}.
      * 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

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -17,16 +17,18 @@
 package org.apache.sis.storage.netcdf;
 
 import java.io.IOException;
+import java.net.URI;
 import org.opengis.metadata.Metadata;
+import org.opengis.parameter.ParameterValueGroup;
 import org.apache.sis.util.Debug;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.UnsupportedStorageException;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.internal.netcdf.Decoder;
+import org.apache.sis.internal.storage.URIDataStore;
 import org.apache.sis.metadata.ModifiableMetadata;
 import org.apache.sis.setup.OptionKey;
-import org.apache.sis.storage.Resource;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Version;
 import ucar.nc2.constants.CDM;
@@ -52,6 +54,11 @@ public class NetcdfStore extends DataSto
     private final Decoder decoder;
 
     /**
+     * The {@link NetcdfStoreProvider#LOCATION} parameter value, or {@code null} if none.
+     */
+    private final URI location;
+
+    /**
      * The object returned by {@link #getMetadata()}, created when first needed and cached.
      */
     private Metadata metadata;
@@ -84,13 +91,14 @@ public class NetcdfStore extends DataSto
      */
     public NetcdfStore(final NetcdfStoreProvider provider, final StorageConnector connector) throws DataStoreException {
         super(provider, connector);
+        location = connector.getStorageAs(URI.class);
         try {
             decoder = NetcdfStoreProvider.decoder(listeners, connector);
         } catch (IOException e) {
             throw new DataStoreException(e);
         }
         if (decoder == null) {
-            throw new UnsupportedStorageException(super.getLocale(), "NetCDF",
+            throw new UnsupportedStorageException(super.getLocale(), NetcdfStoreProvider.NAME,
                     connector.getStorage(), connector.getOption(OptionKey.OPEN_OPTIONS));
         }
     }
@@ -118,14 +126,19 @@ public class NetcdfStore extends DataSto
     }
 
     /**
-     * This implementation does not provide any resource yet.
+     * Returns the parameters used to open this netCDF data store.
+     * If non-null, the parameters are described by {@link NetcdfStoreProvider#getOpenParameters()}
+     * and contains at least a parameter named {@value NetcdfStoreProvider#LOCATION} with a {@link URI} value.
+     * This method may return {@code null} if the storage input can not be described by a URI
+     * (for example a netCDF file reading directly from a {@link java.nio.channels.ReadableByteChannel}).
      *
-     * @return currently {@code null} (will be implemented in future Apache SIS version).
-     * @throws DataStoreException if an error occurred while reading the data.
+     * @return parameters used for opening this data store, or {@code null} if not available.
+     *
+     * @since 0.8
      */
     @Override
-    public Resource getRootResource() throws DataStoreException {
-        return null;
+    public ParameterValueGroup getOpenParameters() {
+        return URIDataStore.parameters(provider, location);
     }
 
     /**

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=1807628&r1=1807627&r2=1807628&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 Sep  7 16:41:02 2017
@@ -26,6 +26,7 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.UndeclaredThrowableException;
+import org.opengis.parameter.ParameterDescriptorGroup;
 import org.apache.sis.internal.netcdf.Decoder;
 import org.apache.sis.internal.netcdf.Resources;
 import org.apache.sis.internal.netcdf.impl.ChannelDecoder;
@@ -33,6 +34,7 @@ import org.apache.sis.internal.netcdf.uc
 import org.apache.sis.internal.storage.io.ChannelDataInput;
 import org.apache.sis.internal.storage.Capabilities;
 import org.apache.sis.internal.storage.Capability;
+import org.apache.sis.internal.storage.URIDataStore;
 import org.apache.sis.internal.system.SystemListener;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.storage.DataStore;
@@ -67,11 +69,21 @@ import org.apache.sis.util.Version;
 @Capabilities(Capability.READ)
 public class NetcdfStoreProvider extends DataStoreProvider {
     /**
+     * The format name.
+     */
+    static final String NAME = "NetCDF";
+
+    /**
      * The MIME type for NetCDF files.
      */
     static final String MIME_TYPE = "application/x-netcdf";
 
     /**
+     * The parameter descriptor to be returned by {@link #getOpenParameters()}.
+     */
+    private static final ParameterDescriptorGroup OPEN_DESCRIPTOR = URIDataStore.Provider.descriptor(NAME);
+
+    /**
      * The name of the {@link ucar.nc2.NetcdfFile} class, which is {@value}.
      */
     private static final String UCAR_CLASSNAME = "ucar.nc2.NetcdfFile";
@@ -126,7 +138,19 @@ public class NetcdfStoreProvider extends
      */
     @Override
     public String getShortName() {
-        return "NetCDF";
+        return NAME;
+    }
+
+    /**
+     * Returns a description of all parameters accepted by this provider for opening a netCDF file.
+     *
+     * @return description of available parameters for opening a netCDF file.
+     *
+     * @since 0.8
+     */
+    @Override
+    public ParameterDescriptorGroup getOpenParameters() {
+        return OPEN_DESCRIPTOR;
     }
 
     /**

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -28,10 +28,8 @@ import org.apache.sis.util.logging.Warni
  * @version 0.8
  * @since   0.8
  * @module
- *
- * @todo this class may be removed if we refactor {@link FeatureSet} as an abstract class.
  */
-public abstract class AbstractFeatureSet extends AbstractResource implements FeatureSet {
+public abstract class AbstractFeatureSet extends AbstractDataSet implements FeatureSet {
     /**
      * Creates a new resource.
      *

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -16,16 +16,8 @@
  */
 package org.apache.sis.internal.storage;
 
-import org.opengis.geometry.Envelope;
-import org.opengis.metadata.Metadata;
-import org.opengis.metadata.extent.Extent;
-import org.opengis.metadata.extent.GeographicExtent;
-import org.opengis.metadata.extent.GeographicBoundingBox;
-import org.opengis.metadata.identification.Identification;
 import org.apache.sis.storage.Resource;
 import org.apache.sis.storage.DataStore;
-import org.apache.sis.storage.DataStoreException;
-import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.util.logging.WarningListeners;
 
 
@@ -36,8 +28,6 @@ import org.apache.sis.util.logging.Warni
  * @version 0.8
  * @since   0.8
  * @module
- *
- * @todo this class may be removed if we refactor {@link Resource} as an abstract class.
  */
 public abstract class AbstractResource implements Resource {
     /**
@@ -65,42 +55,6 @@ public abstract class AbstractResource i
     }
 
     /**
-     * Returns the spatio-temporal envelope of this resource.
-     * The default implementation computes the union of all {@link GeographicBoundingBox} in the resource metadata,
-     * assuming the {@linkplain org.apache.sis.referencing.CommonCRS#defaultGeographic() default geographic CRS}
-     * (usually WGS 84).
-     *
-     * @return the spatio-temporal resource extent.
-     * @throws DataStoreException if an error occurred while reading or computing the envelope.
-     */
-    @Override
-    public Envelope getEnvelope() throws DataStoreException {
-        final Metadata metadata = getMetadata();
-        GeneralEnvelope bounds = null;
-        if (metadata != null) {
-            for (final Identification identification : metadata.getIdentificationInfo()) {
-                if (identification != null) {                                               // Paranoiac check.
-                    for (final Extent extent : identification.getExtents()) {
-                        if (extent != null) {                                               // Paranoiac check.
-                            for (final GeographicExtent ge : extent.getGeographicElements()) {
-                                if (ge instanceof GeographicBoundingBox) {
-                                    final GeneralEnvelope env = new GeneralEnvelope((GeographicBoundingBox) ge);
-                                    if (bounds == null) {
-                                        bounds = env;
-                                    } else {
-                                        bounds.add(env);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return bounds;
-    }
-
-    /**
      * The set of registered warning listeners for the data store.
      *
      * @return the registered warning listeners for the data store.

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DocumentedStoreProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DocumentedStoreProvider.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DocumentedStoreProvider.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DocumentedStoreProvider.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -21,7 +21,6 @@ import org.opengis.metadata.distribution
 import org.apache.sis.metadata.sql.MetadataSource;
 import org.apache.sis.metadata.sql.MetadataStoreException;
 import org.apache.sis.storage.DataStore;
-import org.apache.sis.storage.DataStoreProvider;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.logging.WarningListeners;
 import org.apache.sis.internal.system.Modules;
@@ -36,7 +35,7 @@ import org.apache.sis.internal.system.Mo
  * @since   0.8
  * @module
  */
-public abstract class DocumentedStoreProvider extends DataStoreProvider {
+public abstract class DocumentedStoreProvider extends URIDataStore.Provider {
     /**
      * The primary key to use for searching in the {@code MD_Format} table, or {@code null} if none.
      * This primary name is also the value returned by {@link #getShortName()} default implementation.

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -164,11 +164,26 @@ public final class Resources extends Ind
         public static final short ShallBeDeclaredBefore_2 = 22;
 
         /**
+         * Write operations are not supported.
+         */
+        public static final short StoreIsReadOnly = 28;
+
+        /**
          * Can not move backward in the “{0}” stream.
          */
         public static final short StreamIsForwardOnly_1 = 13;
 
         /**
+         * Stream “{0}” is not readable.
+         */
+        public static final short StreamIsNotReadable_1 = 25;
+
+        /**
+         * Stream “{0}” is not writable.
+         */
+        public static final short StreamIsNotWritable_1 = 26;
+
+        /**
          * The “{0}” data store can be read only once.
          */
         public static final short StreamIsReadOnce_1 = 18;
@@ -179,6 +194,11 @@ public final class Resources extends Ind
         public static final short StreamIsWriteOnce_1 = 21;
 
         /**
+         * Can not open {0} data store without “{1}” parameter.
+         */
+        public static final short UndefinedParameter_2 = 27;
+
+        /**
          * Format of “{0}” is not recognized.
          */
         public static final short UnknownFormatFor_1 = 14;

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties [ISO-8859-1] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties [ISO-8859-1] Thu Sep  7 16:41:02 2017
@@ -39,7 +39,11 @@ ProcessingExecutedOn_1            = Proc
 ResourceIdentifierCollision_2     = More than one resource have the \u201c{1}\u201d identifier in the \u201c{0}\u201d data store.
 ResourceNotFound_2                = No resource found for the \u201c{1}\u201d identifier in the \u201c{0}\u201d data store.
 ShallBeDeclaredBefore_2           = The \u201c{1}\u201d element must be declared before \u201c{0}\u201d.
+StoreIsReadOnly                   = Write operations are not supported.
 StreamIsForwardOnly_1             = Can not move backward in the \u201c{0}\u201d stream.
+StreamIsNotReadable_1             = Stream \u201c{0}\u201d is not readable.
+StreamIsNotWritable_1             = Stream \u201c{0}\u201d is not writable.
 StreamIsReadOnce_1                = The \u201c{0}\u201d data store can be read only once.
 StreamIsWriteOnce_1               = Can not modify previously written data in \u201c{0}\u201d.
+UndefinedParameter_2              = Can not open {0} data store without \u201c{1}\u201d parameter.
 UnknownFormatFor_1                = Format of \u201c{0}\u201d is not recognized.

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties [ISO-8859-1] Thu Sep  7 16:41:02 2017
@@ -44,7 +44,11 @@ ProcessingExecutedOn_1            = Trai
 ResourceIdentifierCollision_2     = Plusieurs ressources utilisent l\u2019identifiant \u00ab\u202f{1}\u202f\u00bb dans les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb.
 ResourceNotFound_2                = Aucune ressource n\u2019a \u00e9t\u00e9 trouv\u00e9e pour l\u2019identifiant \u00ab\u202f{1}\u202f\u00bb dans les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb.
 ShallBeDeclaredBefore_2           = L\u2019\u00e9l\u00e9ment \u00ab\u202f{1}\u202f\u00bb doit \u00eatre d\u00e9clar\u00e9 avant \u00ab\u202f{0}\u202f\u00bb.
+StoreIsReadOnly                   = Les op\u00e9rations d\u2019\u00e9criture ne sont pas support\u00e9es.
 StreamIsForwardOnly_1             = Ne peut pas reculer dans le flux de donn\u00e9es \u00ab\u202f{0}\u202f\u00bb.
+StreamIsNotReadable_1             = Les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb ne sont pas accessibles en lecture.
+StreamIsNotWritable_1             = Le flux de donn\u00e9es \u00ab\u202f{0}\u202f\u00bb ne g\u00e8re pas les \u00e9critures.
 StreamIsReadOnce_1                = Les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb ne peuvent \u00eatre lues qu\u2019une seule fois.
 StreamIsWriteOnce_1               = Ne peut pas revenir sur les donn\u00e9es d\u00e9j\u00e0 \u00e9crites dans \u00ab\u202f{0}\u202f\u00bb.
+UndefinedParameter_2              = Ne peut pas ouvrir une source de donn\u00e9es {0} sans le param\u00e8tre \u00ab\u202f{1}\u202f\u00bb.
 UnknownFormatFor_1                = Le format de \u00ab\u202f{0}\u202f\u00bb n\u2019est pas reconnu.

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -30,8 +30,9 @@ import java.net.URI;
 import java.nio.charset.Charset;
 import javax.measure.Unit;
 import javax.measure.quantity.Time;
-import org.opengis.metadata.Metadata;
 import org.opengis.util.FactoryException;
+import org.opengis.geometry.Envelope;
+import org.opengis.metadata.Metadata;
 import org.opengis.metadata.maintenance.ScopeCode;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.TemporalCRS;
@@ -47,15 +48,17 @@ import org.apache.sis.internal.storage.i
 import org.apache.sis.internal.feature.Geometries;
 import org.apache.sis.internal.feature.MovingFeature;
 import org.apache.sis.internal.storage.Resources;
+import org.apache.sis.internal.storage.URIDataStore;
 import org.apache.sis.geometry.GeneralEnvelope;
+import org.apache.sis.geometry.ImmutableEnvelope;
 import org.apache.sis.metadata.iso.DefaultMetadata;
 import org.apache.sis.metadata.sql.MetadataStoreException;
-import org.apache.sis.storage.Resource;
-import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreContentException;
 import org.apache.sis.storage.DataStoreReferencingException;
+import org.apache.sis.storage.UnsupportedStorageException;
 import org.apache.sis.storage.StorageConnector;
+import org.apache.sis.storage.FeatureSet;
 import org.apache.sis.setup.OptionKey;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.CharSequences;
@@ -82,7 +85,7 @@ import org.opengis.feature.AttributeType
  * @since   0.7
  * @module
  */
-public final class Store extends DataStore {
+public final class Store extends URIDataStore implements FeatureSet {
     /**
      * The character at the beginning of lines to ignore in the header.
      * Note that this is not part of OGC Moving Feature Specification.
@@ -152,8 +155,9 @@ public final class Store extends DataSto
      * and a temporal component if the CSV file contains a start time and end time.
      *
      * @see #parseEnvelope(List)
+     * @see #getEnvelope()
      */
-    private final GeneralEnvelope envelope;
+    private final ImmutableEnvelope envelope;
 
     /**
      * Description of the columns found in the CSV file.
@@ -230,7 +234,8 @@ public final class Store extends DataSto
         final Reader r = connector.getStorageAs(Reader.class);
         connector.closeAllExcept(r);
         if (r == null) {
-            throw new DataStoreException(Errors.format(Errors.Keys.CanNotOpen_1, super.getDisplayName()));
+            throw new UnsupportedStorageException(super.getLocale(), StoreProvider.NAME,
+                    connector.getStorage(), connector.getOption(OptionKey.OPEN_OPTIONS));
         }
         source = (r instanceof BufferedReader) ? (BufferedReader) r : new LineNumberReader(r);
         geometries = Geometries.implementation(connector.getOption(OptionKey.GEOMETRY_LIBRARY));
@@ -297,7 +302,7 @@ public final class Store extends DataSto
             throw new DataStoreContentException(getLocale(), StoreProvider.NAME, super.getDisplayName(), source).initCause(e);
         }
         this.encoding    = connector.getOption(OptionKey.ENCODING);
-        this.envelope    = envelope;
+        this.envelope    = new ImmutableEnvelope(envelope);
         this.featureType = featureType;
         this.foliation   = foliation;
         this.dissociate |= (timeEncoding == null);
@@ -618,13 +623,29 @@ public final class Store extends DataSto
     }
 
     /**
-     * Returns the {@code FeatureSet} from which all features in this data store can be accessed.
+     * Returns the spatio-temporal extent of CSV data in coordinate reference system of the CSV file.
+     */
+    @Override
+    public Envelope getEnvelope() throws DataStoreException {
+        return envelope;
+    }
+
+    /**
+     * Returns the type of features in the CSV file. The feature type name will be the value
+     * specified at the following path (only one such value exists for a CSV data store):
      *
-     * @return the starting point of all features in this data store.
+     * <blockquote>
+     * {@link #getMetadata()} /
+     * {@link org.apache.sis.metadata.iso.DefaultMetadata#getContentInfo() contentInfo} /
+     * {@link org.apache.sis.metadata.iso.content.DefaultFeatureCatalogueDescription#getFeatureTypeInfo() featureTypes} /
+     * {@link org.apache.sis.metadata.iso.content.DefaultFeatureTypeInfo#getFeatureTypeName() featureTypeName}
+     * </blockquote>
+     *
+     * @return type of features in the CSV file.
      */
     @Override
-    public Resource getRootResource() {
-        return new FeatureAccess(this, listeners);
+    public FeatureType getType() {
+        return featureType;
     }
 
     /**
@@ -637,7 +658,8 @@ public final class Store extends DataSto
      * @todo Needs to reset the position when doing another pass on the features.
      * @todo If sequential order, publish Feature as soon as identifier changed.
      */
-    final synchronized Stream<Feature> features(final boolean parallel) throws DataStoreException {
+    @Override
+    public final synchronized Stream<Feature> features(final boolean parallel) throws DataStoreException {
         /*
          * If the user asks for one feature instance per line, then we can return a FeatureIter instance directly.
          * Since each feature is fully constructed from a single line and each line are read atomically, we can

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -18,11 +18,11 @@ package org.apache.sis.internal.storage.
 
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
-import org.apache.sis.storage.DataStoreProvider;
 import org.apache.sis.storage.ProbeResult;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.internal.storage.Capability;
 import org.apache.sis.internal.storage.Capabilities;
+import org.apache.sis.internal.storage.URIDataStore;
 import org.apache.sis.internal.storage.wkt.FirstKeywordPeek;
 
 
@@ -40,7 +40,7 @@ import org.apache.sis.internal.storage.w
  * @module
  */
 @Capabilities(Capability.READ)
-public final class StoreProvider extends DataStoreProvider {
+public final class StoreProvider extends URIDataStore.Provider {
     /**
      * The format names for static features and moving features.
      */

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelData.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelData.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelData.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelData.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -62,8 +62,11 @@ public abstract class ChannelData implem
      * The position of the channel when this {@code ChannelData} has been created.
      * This is almost always 0, but we allow other values in case the data to read
      * or write are part of a bigger file.
+     *
+     * <p>This value is added to the argument given to the {@link #seek(long)} method. Users can ignore
+     * this field, unless they want to invoke {@link SeekableByteChannel#position(long)} directly.</p>
      */
-    final long channelOffset;
+    public final long channelOffset;
 
     /**
      * The channel position where is located the {@link #buffer} value at index 0.
@@ -272,13 +275,11 @@ public abstract class ChannelData implem
      * An {@code IOException} may be be thrown if the previous marked position lies in the
      * discarded portion of the stream.
      *
-     * <p>This method differs from the {@link javax.imageio.stream.ImageInputStream} contract in two aspects:</p>
-     * <ul>
-     *   <li>This method may, under some conditions, be able to perform its work even if the marked
-     *       position is before the flushed position.</li>
-     *   <li>If there is no mark, this method throws an {@link InvalidMarkException} rather than
-     *       doing nothing. Doing nothing is considered a too high risk of error.</li>
-     * </ul>
+     * <div class="section">Departure from Image I/O specification</div>
+     * The {@link javax.imageio.stream.ImageInputStream#reset()} contract specifies that if there is no matching mark,
+     * then this method shall do nothing. This method throws {@link InvalidMarkException} instead; silently ignoring
+     * the mismatch is considered too dangerous. However we may revisit this policy in the future if it appears to be
+     * a compatibility problem. Consequently, no code shall rely on {@code InvalidMarkException} to be thrown.
      *
      * @throws IOException if an I/O error occurs.
      */

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -844,7 +844,7 @@ public class ChannelDataInput extends Ch
      */
     @Override
     public final void seek(final long position) throws IOException {
-        long p = position - bufferOffset;
+        long p = JDK8.subtractExact(position, bufferOffset);
         if (p >= 0 && p <= buffer.limit()) {
             /*
              * Requested position is inside the current limits of the buffer.
@@ -857,7 +857,7 @@ public class ChannelDataInput extends Ch
              * that StorageConnector.rewind() needs the buffer content to be
              * valid as a result of this seek, so we reload it immediately.
              */
-            ((SeekableByteChannel) channel).position(channelOffset + position);
+            ((SeekableByteChannel) channel).position(JDK8.addExact(channelOffset, position));
             bufferOffset = position;
             buffer.clear().limit(0);
         } else if (p >= 0) {

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataOutput.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataOutput.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataOutput.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataOutput.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -33,6 +33,9 @@ import org.apache.sis.internal.storage.R
 
 import static org.apache.sis.util.ArgumentChecks.ensureBetween;
 
+// Branch-dependent imports
+import org.apache.sis.internal.jdk8.JDK8;
+
 
 /**
  * Provides convenience methods for working with a ({@link WritableByteChannel}, {@link ByteBuffer}) pair.
@@ -607,7 +610,7 @@ public class ChannelDataOutput extends C
      */
     @Override
     public final void seek(final long position) throws IOException {
-        long p = position - bufferOffset;
+        long p = JDK8.subtractExact(position, bufferOffset);
         if (p >= 0 && p <= buffer.limit()) {
             /*
              * Requested position is inside the current limits of the buffer.
@@ -620,7 +623,7 @@ public class ChannelDataOutput extends C
              * but we can set the new position directly in the channel.
              */
             flush();
-            ((SeekableByteChannel) channel).position(channelOffset + position);
+            ((SeekableByteChannel) channel).position(JDK8.addExact(channelOffset, position));
             bufferOffset = position;
         } else if (p >= 0) {
             /*

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -45,6 +45,8 @@ import org.apache.sis.util.logging.Loggi
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.storage.Resources;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.ForwardOnlyStorageException;
 
 
 /**
@@ -244,6 +246,18 @@ public abstract class ChannelFactory {
     }
 
     /**
+     * Returns whether the streams or channels created by this factory is coupled with the {@code storage} argument
+     * given to the {@link #prepare prepare(…)} method. This is {@code true} if the storage is an {@link InputStream},
+     * {@link OutputStream} or {@link Channel}, and {@code false} if the storage is a {@link Path}, {@link File},
+     * {@link URL}, {@link URI} or equivalent.
+     *
+     * @return whether using the streams or channels will affect the original {@code storage} object.
+     */
+    public boolean isCoupled() {
+        return false;
+    }
+
+    /**
      * Returns {@code true} if this factory is capable to create another reader. This method returns {@code false}
      * if this factory is capable to create only one channel and {@link #reader(String)} has already been invoked.
      *
@@ -259,9 +273,10 @@ public abstract class ChannelFactory {
      *
      * @param  filename  data store name to report in case of failure.
      * @return the input stream.
+     * @throws DataStoreException if the channel is read-once.
      * @throws IOException if the input stream or its underlying byte channel can not be created.
      */
-    public InputStream inputStream(final String filename) throws IOException {
+    public InputStream inputStream(final String filename) throws DataStoreException, IOException {
         return Channels.newInputStream(reader(filename));
     }
 
@@ -271,9 +286,10 @@ public abstract class ChannelFactory {
      *
      * @param  filename  data store name to report in case of failure.
      * @return the output stream.
+     * @throws DataStoreException if the channel is write-once.
      * @throws IOException if the output stream or its underlying byte channel can not be created.
      */
-    public OutputStream outputStream(final String filename) throws IOException {
+    public OutputStream outputStream(final String filename) throws DataStoreException, IOException {
         return Channels.newOutputStream(writer(filename));
     }
 
@@ -284,9 +300,10 @@ public abstract class ChannelFactory {
      *
      * @param  filename  data store name to report in case of failure.
      * @return the channel for the given input.
+     * @throws DataStoreException if the channel is read-once.
      * @throws IOException if an error occurred while opening the channel.
      */
-    public abstract ReadableByteChannel reader(String filename) throws IOException;
+    public abstract ReadableByteChannel reader(String filename) throws DataStoreException, IOException;
 
     /**
      * Returns a byte channel from the output given to the {@link #prepare prepare(…)} method.
@@ -295,9 +312,10 @@ public abstract class ChannelFactory {
      *
      * @param  filename  data store name to report in case of failure.
      * @return the channel for the given output.
+     * @throws DataStoreException if the channel is write-once.
      * @throws IOException if an error occurred while opening the channel.
      */
-    public abstract WritableByteChannel writer(String filename) throws IOException;
+    public abstract WritableByteChannel writer(String filename) throws DataStoreException, IOException;
 
     /**
      * A factory that returns an existing channel <cite>as-is</cite>.
@@ -317,6 +335,14 @@ public abstract class ChannelFactory {
         }
 
         /**
+         * Returns {@code true} since use of channels or streams will affect the original storage object.
+         */
+        @Override
+        public boolean isCoupled() {
+            return true;
+        }
+
+        /**
          * Returns whether {@link #reader(String)} or {@link #writer(String)} can be invoked.
          */
         @Override
@@ -329,13 +355,19 @@ public abstract class ChannelFactory {
          * throws an exception on all subsequent invocations.
          */
         @Override
-        public ReadableByteChannel reader(final String filename) throws IOException {
+        public ReadableByteChannel reader(final String filename) throws DataStoreException, IOException {
             final Channel in = channel;
             if (in instanceof ReadableByteChannel) {
                 channel = null;
                 return (ReadableByteChannel) in;
             }
-            throw new IOException(Resources.format(Resources.Keys.StreamIsReadOnce_1, filename));
+            String message = Resources.format(in != null ? Resources.Keys.StreamIsNotReadable_1
+                                                         : Resources.Keys.StreamIsReadOnce_1, filename);
+            if (in != null) {
+                throw new IOException(message);                     // Stream is not readable.
+            } else {
+                throw new ForwardOnlyStorageException(message);     // Stream has already been read.
+            }
         }
 
         /**
@@ -343,13 +375,19 @@ public abstract class ChannelFactory {
          * throws an exception on all subsequent invocations.
          */
         @Override
-        public WritableByteChannel writer(final String filename) throws IOException {
-            final Channel in = channel;
-            if (in instanceof WritableByteChannel) {
+        public WritableByteChannel writer(final String filename) throws DataStoreException, IOException {
+            final Channel out = channel;
+            if (out instanceof WritableByteChannel) {
                 channel = null;
-                return (WritableByteChannel) in;
+                return (WritableByteChannel) out;
+            }
+            String message = Resources.format(out != null ? Resources.Keys.StreamIsNotWritable_1
+                                                          : Resources.Keys.StreamIsWriteOnce_1, filename);
+            if (out != null) {
+                throw new IOException(message);                     // Stream is not writable.
+            } else {
+                throw new ForwardOnlyStorageException(message);     // Stream has already been written.
             }
-            throw new IOException(Resources.format(Resources.Keys.StreamIsWriteOnce_1, filename));
         }
     }
 
@@ -357,7 +395,7 @@ public abstract class ChannelFactory {
      * A factory used as a fallback when we failed to convert a {@link File} to a {@link Path}.
      * This is used only if the conversion attempt threw an {@link InvalidPathException}. Such
      * failure is unlikely to happen, but if it happens anyway we try to open the channel in a
-     * way less surprising for the user (closer to the object he has specified).
+     * less surprising way for the user (i.e. closer to the object (s)he has specified).
      */
     private static final class Fallback extends ChannelFactory {
         /**

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelImageInputStream.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelImageInputStream.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelImageInputStream.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelImageInputStream.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -347,6 +347,14 @@ loop:   while ((c = read()) >= 0) {
 
     /**
      * Closes the {@linkplain #channel}.
+     * If the channel is backed by an {@link java.io.InputStream}, that stream will be closed too.
+     *
+     * <div class="section">Departure from Image I/O standard implementation</div>
+     * Java Image I/O wrappers around input/output streams do not close the underlying stream (see for example
+     * {@link javax.imageio.stream.FileCacheImageInputStream#close()} specification). But Apache SIS needs the
+     * underlying stream to be closed because we do not keep reference to the original input stream. Note that
+     * channels created by {@link java.nio.channels.Channels#newChannel(java.io.InputStream)} close the stream,
+     * which is the desired behavior for this method.
      *
      * @throws IOException if an error occurred while closing the channel.
      */

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java?rev=1807628&r1=1807627&r2=1807628&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java [UTF-8] Thu Sep  7 16:41:02 2017
@@ -20,6 +20,7 @@ import java.util.Locale;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.LineNumberReader;
+import java.io.Reader;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.IOException;
@@ -239,7 +240,7 @@ public final class IOUtilities extends S
             return null;
         }
         /*
-         * Convert the URL to an URI, taking in account the encoding if any.
+         * Convert the URL to a URI, taking in account the encoding if any.
          *
          * Note: URL.toURI() is implemented as new URI(URL.toString()) where toString()
          * delegates to toExternalForm(), and all those methods are final. So we really
@@ -531,6 +532,30 @@ public final class IOUtilities extends S
     }
 
     /**
+     * Reads the next character as an Unicode code point. Unless end-of-file has been reached, the returned value is
+     * between {@value java.lang.Character#MIN_CODE_POINT} and {@value java.lang.Character#MAX_CODE_POINT} inclusive.
+     *
+     * @param  in  the reader from which to read code point.
+     * @return the next code point, or -1 on end of file.
+     * @throws IOException if an error occurred while reading characters.
+     *
+     * @since 0.8
+     */
+    public static int readCodePoint(final Reader in) throws IOException {
+        int c = in.read();
+        while (c >= Character.MIN_HIGH_SURROGATE && c <= Character.MAX_HIGH_SURROGATE) {
+            final int low = in.read();
+            if (low >= Character.MIN_LOW_SURROGATE && low <= Character.MAX_LOW_SURROGATE) {
+                c = Character.toCodePoint((char) c, (char) low);
+                break;
+            } else {
+                c = low;        // Discard orphan high surrogate and take the next character.
+            }
+        }
+        return c;
+    }
+
+    /**
      * Returns the error message for a file that can not be parsed.
      * The error message will contain the line number if available.
      *



Mime
View raw message