Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id DBC45200CF0 for ; Thu, 7 Sep 2017 18:41:10 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id DB85B16098B; Thu, 7 Sep 2017 16:41:10 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id A070A1609D7 for ; Thu, 7 Sep 2017 18:41:08 +0200 (CEST) Received: (qmail 45507 invoked by uid 500); 7 Sep 2017 16:41:07 -0000 Mailing-List: contact commits-help@sis.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: sis-dev@sis.apache.org Delivered-To: mailing list commits@sis.apache.org Received: (qmail 45494 invoked by uid 99); 7 Sep 2017 16:41:07 -0000 Received: from Unknown (HELO svn01-us-west.apache.org) (209.188.14.144) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 07 Sep 2017 16:41:07 +0000 Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id 58CBE3A02E8 for ; Thu, 7 Sep 2017 16:41:06 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 -0000 To: commits@sis.apache.org From: desruisseaux@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20170907164106.58CBE3A02E8@svn01-us-west.apache.org> archived-at: Thu, 07 Sep 2017 16:41:11 -0000 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 * * * - * + * *
SI angle units: {@link #MICRORADIAN}, {@code RADIAN}.
In other systems: {@link #DEGREE}, {@link #ARC_MINUTE}, {@link #ARC_SECOND}, {@link #GRAD}.
Derived units: {@link #STERADIAN}.
Derived units: {@link #STERADIAN}, {@link #RADIANS_PER_SECOND}.
* * @since 0.8 @@ -582,6 +582,19 @@ public final class Units extends Static public static final Unit HERTZ; /** + * The unit for angular velocity (rad/s). + * The identifier is EPSG:1035. + * + *

Related units:

+ * + * + *
Components: {@link #RADIAN} ∕ {@link #SECOND}
+ * + * @since 0.8 + */ + public static final Unit 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. * - *

If we make this field public in a future SIS version, we should consider introducing a - * {@code Salinity} quantity type.

+ * @since 0.8 */ - static final Unit PSU; + public static final Unit 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. - */ + * All Unit, Unit and Unit. + * 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 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. */ @@ -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() {@Override public Frequency create(double value, Unit unit) {return new Scalar.Frequency(value, unit);}}, time.pow(-1), "Hz", (byte) (SI | PREFIXABLE), (short) 0); - NEWTON = add(Force.class, new ScalarFactory () {@Override public Force create(double value, Unit unit) {return new Scalar.Force (value, unit);}}, force, "N", (byte) (SI | PREFIXABLE), (short) 0); - JOULE = add(Energy.class, new ScalarFactory () {@Override public Energy create(double value, Unit unit) {return new Scalar.Energy (value, unit);}}, energy, "J", (byte) (SI | PREFIXABLE), (short) 0); - WATT = add(Power.class, new ScalarFactory () {@Override public Power create(double value, Unit unit) {return new Scalar.Power (value, unit);}}, power, "W", (byte) (SI | PREFIXABLE), (short) 0); + HERTZ = add(Frequency.class, new ScalarFactory() {@Override public Frequency create(double value, Unit unit) {return new Scalar.Frequency(value, unit);}}, frequency, "Hz", (byte) (SI | PREFIXABLE), (short) 0); + NEWTON = add(Force.class, new ScalarFactory () {@Override public Force create(double value, Unit unit) {return new Scalar.Force (value, unit);}}, force, "N", (byte) (SI | PREFIXABLE), (short) 0); + JOULE = add(Energy.class, new ScalarFactory () {@Override public Energy create(double value, Unit unit) {return new Scalar.Energy (value, unit);}}, energy, "J", (byte) (SI | PREFIXABLE), (short) 0); + WATT = add(Power.class, new ScalarFactory () {@Override public Power create(double value, Unit 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 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 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: * *
    - *
  • If the {@link XLink#getHRef() xlink:href} attribute is an {@linkplain URI#getFragment() URI fragment} + *
  • 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.
  • *
  • Otherwise returns {@code null}.
  • 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 @@ + + + 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 maven-javadoc-plugin - 2.10.4 + 2.10.4 ${maven.compile.source} ${project.build.sourceEncoding} 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: *
      - *
    • {@code "+init=epsg:3395"} (see warning below)
    • + *
    • {@code "+init=epsg:3395 +over"} (see warning below)
    • *
    • {@code "+proj=latlong +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"}
    • *
    • {@code "+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +ellps=WGS84 +towgs84=0,0,0"}
    • *
    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. + *
      + *
    • 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.
    • + *
    • 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.
    • + *
    + */ + 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. + *
    + * {@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} + *
    + * + * @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 features(final boolean parallel) throws DataStoreException { + @Override + public final synchronized Stream 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. + * + *

    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.

    */ - 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. * - *

    This method differs from the {@link javax.imageio.stream.ImageInputStream} contract in two aspects:

    - *
      - *
    • This method may, under some conditions, be able to perform its work even if the marked - * position is before the flushed position.
    • - *
    • 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.
    • - *
    + *
    Departure from Image I/O specification
    + * 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 as-is. @@ -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. + * + *
    Departure from Image I/O standard implementation
    + * 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. *