This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit d4de6823223b34a1220e03b387b760fec4940f33 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Fri Oct 4 12:43:38 2024 +0200 Reduce the amount of logs emitted when the EPSG database is not available. CommonCRS synchronization has been made less fine-grained (which also simplifies the code) because the previous strategy did not prevent duplicated log record under race conditions. The results were correct, but the duplicated log records were confusing. --- .../sis/metadata/sql/privy/LocalDataSource.java | 6 +- .../main/org/apache/sis/xml/XML.java | 2 +- .../main/org/apache/sis/xml/bind/Context.java | 1 + .../main/org/apache/sis/io/wkt/Warnings.java | 2 +- .../apache/sis/referencing/AuthorityFactories.java | 23 +- .../main/org/apache/sis/referencing/CommonCRS.java | 324 +++++++++------------ .../factory/ConcurrentAuthorityFactory.java | 2 +- .../factory/IdentifiedObjectFinder.java | 14 +- .../sis/referencing/factory/sql/EPSGFactory.java | 15 +- .../sis/referencing/factory/sql/EPSGInstaller.java | 5 +- .../referencing/internal/ServicesForMetadata.java | 3 +- .../operation/builder/ProjectedTransformTry.java | 3 +- .../apache/sis/geometry/DirectPosition1DTest.java | 4 +- .../main/org/apache/sis/io/stream/IOUtilities.java | 5 +- .../apache/sis/storage/event/StoreListeners.java | 10 +- .../main/org/apache/sis/system/DataDirectory.java | 3 +- .../main/org/apache/sis/util/Exceptions.java | 24 +- .../main/org/apache/sis/util/logging/Logging.java | 6 +- .../sis/util/resources/IndexedResourceBundle.java | 18 +- .../test/org/apache/sis/test/Assertions.java | 5 +- .../sis/storage/gsf/panama/LibraryLoader.java | 4 +- .../apache/sis/gui/referencing/AuthorityCodes.java | 3 +- .../apache/sis/storage/panama/LibraryLoader.java | 4 +- .../org/apache/sis/storage/panama/Resources.java | 2 +- .../apache/sis/storage/panama/Resources.properties | 2 +- .../sis/storage/panama/Resources_fr.properties | 2 +- 26 files changed, 221 insertions(+), 271 deletions(-) diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/LocalDataSource.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/LocalDataSource.java index ee01414623..5e18c53a63 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/LocalDataSource.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/LocalDataSource.java @@ -290,7 +290,7 @@ public final class LocalDataSource implements DataSource, Comparable<LocalDataSo } } } catch (SQLException e) { // This is the expected exception. - final LogRecord record = new LogRecord(Level.FINE, e.getMessage()); + final var record = new LogRecord(Level.FINER, e.getMessage()); if (dialect != Dialect.DERBY || !isSuccessfulShutdown(e)) { record.setLevel(Level.WARNING); record.setThrown(e); @@ -311,8 +311,8 @@ public final class LocalDataSource implements DataSource, Comparable<LocalDataSo */ public static boolean isSuccessfulShutdown(final SQLException e) { final String state = e.getSQLState(); - return "08006".equals(state) || // Database "SpatialMetadata" shutdown. - "XJ004".equals(state); // Database "SpatialMetadata" not found (may happen if we failed to open it in the first place). + return "08006".equals(state) || // Database shutdown. + "XJ004".equals(state); // Database not found (may happen if we failed to open it in the first place). } /** diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/XML.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/XML.java index 01f5a5f070..80958b3447 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/XML.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/XML.java @@ -367,7 +367,7 @@ public final class XML extends Static { * Specifies a listener to be notified when a non-fatal error occurred during the (un)marshalling. * The value for this property shall be an instance of {@link Filter}. * - * <p>By default, warnings that occur during the (un)marshalling process are logged. However if a + * <p>By default, warnings that occur during the (un)marshalling process are logged. However, if a * property is set for this key, then the {@link Filter#isLoggable(LogRecord)} method will be invoked. * If that method returns {@code false}, then the warning will not be logged by the (un)marshaller.</p> * diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/Context.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/Context.java index 30891b3244..006ebf9d9f 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/Context.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/Context.java @@ -837,6 +837,7 @@ public final class Context extends MarshalContext { if (!logFilter.isLoggable(record)) { return; } + record.setThrown(null); } } /* diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Warnings.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Warnings.java index 846c5f7bfe..095fec6c37 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Warnings.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Warnings.java @@ -363,7 +363,7 @@ public final class Warnings implements Localized, Serializable { if (cause != null) { String details = Exceptions.getLocalizedMessage(cause, locale); if (details == null) { - details = cause.toString(); + details = Classes.getShortClassName(cause); } buffer.append(lineSeparator).append(" ").append(details); } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AuthorityFactories.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AuthorityFactories.java index 8b5d66f2dd..7ecce9566b 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AuthorityFactories.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AuthorityFactories.java @@ -206,19 +206,20 @@ final class AuthorityFactories<T extends AuthorityFactory> extends LazySet<T> { */ static boolean isUnavailable(final UnavailableFactoryException e) { final AuthorityFactory unavailable = e.getUnavailableFactory(); - if (!(unavailable instanceof EPSGFactoryFallback)) { - if (e.getCause() instanceof SQLTransientException) { - return false; - } - synchronized (AuthorityFactories.class) { - if (unavailable == EPSG) { - ALL.reload(); // Must be before setting the `EPSG` field. - EPSG = EPSGFactoryFallback.INSTANCE; - return false; - } + if (unavailable instanceof EPSGFactoryFallback) { + return true; + } + if (e.getCause() instanceof SQLTransientException) { + // Not definitive, but caller should still throw an exception or log a warning. + return true; + } + synchronized (AuthorityFactories.class) { + if (unavailable == EPSG) { + ALL.reload(); // Must be before setting the `EPSG` field. + EPSG = EPSGFactoryFallback.INSTANCE; } } - return true; + return false; } /** diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java index 68d218eee4..33edfaf6e3 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java @@ -359,35 +359,35 @@ public enum CommonCRS { * on which method has been invoked. The kind of object stored in this field may change during the * application execution. */ - private transient volatile IdentifiedObject cached; + private transient IdentifiedObject cached; /** * The normalized geographic CRS, created when first needed. * * @see #normalizedGeographic() */ - private transient volatile GeographicCRS cachedNormalized; + private transient GeographicCRS cachedNormalized; /** * The three-dimensional geographic CRS, created when first needed. * * @see #geographic3D() */ - private transient volatile GeographicCRS cachedGeo3D; + private transient GeographicCRS cachedGeo3D; /** * The geocentric CRS using Cartesian coordinate system, created when first needed. * * @see #geocentric() */ - private transient volatile GeodeticCRS cachedGeocentric; + private transient GeodeticCRS cachedGeocentric; /** * The geocentric CRS using spherical coordinate system, created when first needed. * * @see #spherical() */ - private transient volatile GeodeticCRS cachedSpherical; + private transient GeodeticCRS cachedSpherical; /** * The Universal Transverse Mercator (UTM) or Universal Polar Stereographic (UPS) projections, @@ -455,6 +455,7 @@ public enum CommonCRS { cachedGeo3D = null; cachedNormalized = null; cachedGeocentric = null; + cachedSpherical = null; synchronized (cachedProjections) { cachedProjections.clear(); } @@ -601,19 +602,19 @@ public enum CommonCRS { * @see DefaultGeographicCRS#forConvention(AxesConvention) * @see AxesConvention#NORMALIZED */ - public GeographicCRS normalizedGeographic() { - GeographicCRS object = cachedNormalized; - if (object == null) { + public synchronized GeographicCRS normalizedGeographic() { + /* + * Note on synchronization: a previous version of this class was using volatile fields for the caches, + * and kept the synchronized blocks as small as possible. It has been replaced by simpler synchronized + * methods in order to avoid race conditions which resulted in duplicated and confusing log messages + * when the EPSG factory is not available. + */ + if (cachedNormalized == null) { DefaultGeographicCRS crs = DefaultGeographicCRS.castOrCopy(geographic()); crs = crs.forConvention(AxesConvention.RIGHT_HANDED); // Equivalent to NORMALIZED in our cases, but faster. - synchronized (this) { - object = cachedNormalized; - if (object == null) { - cachedNormalized = object = crs; - } - } + cachedNormalized = crs; } - return object; + return cachedNormalized; } /** @@ -641,12 +642,11 @@ public enum CommonCRS { * @see CRS#forCode(String) * @see DefaultGeographicCRS */ - public GeographicCRS geographic() { + public synchronized GeographicCRS geographic() { GeographicCRS object = geographic(cached); if (object == null) { final GeodeticAuthorityFactory factory = factory(); if (factory != null) try { - // Synchronization provided by the cache of the factory. cached = object = factory.createGeographicCRS(String.valueOf(geographic)); return object; } catch (FactoryException e) { @@ -658,20 +658,13 @@ public enum CommonCRS { * We will arbitrarily create this CS only for the most frequently created CRS, * and share that CS instance for all other constants. */ - EllipsoidalCS cs = null; + final EllipsoidalCS cs; if (this != DEFAULT) { cs = DEFAULT.geographic().getCoordinateSystem(); + } else { + cs = (EllipsoidalCS) StandardDefinitions.createCoordinateSystem(StandardDefinitions.ELLIPSOIDAL_2D, true); } - synchronized (this) { - object = geographic(cached); - if (object == null) { - if (cs == null) { - cs = (EllipsoidalCS) StandardDefinitions.createCoordinateSystem(StandardDefinitions.ELLIPSOIDAL_2D, true); - } - object = StandardDefinitions.createGeographicCRS(geographic, frame, cs); - cached = object; - } - } + cached = object = StandardDefinitions.createGeographicCRS(geographic, frame, cs); } return object; } @@ -700,15 +693,12 @@ public enum CommonCRS { * @see CRS#forCode(String) * @see DefaultGeographicCRS */ - public GeographicCRS geographic3D() { - GeographicCRS object = cachedGeo3D; - if (object == null) { + public synchronized GeographicCRS geographic3D() { + if (cachedGeo3D == null) { if (geo3D != 0) { final GeodeticAuthorityFactory factory = factory(); if (factory != null) try { - // Synchronization provided by the cache of the factory. - cachedGeo3D = object = factory.createGeographicCRS(String.valueOf(geo3D)); - return object; + return cachedGeo3D = factory.createGeographicCRS(String.valueOf(geo3D)); } catch (FactoryException e) { failure(this, "geographic3D", e, geo3D); } @@ -719,23 +709,16 @@ public enum CommonCRS { * We will arbitrarily create this CS only for the most frequently created CRS, * and share that CS instance for all other constants. */ - EllipsoidalCS cs = null; + final EllipsoidalCS cs; if (this != DEFAULT) { cs = DEFAULT.geographic3D().getCoordinateSystem(); + } else { + cs = (EllipsoidalCS) StandardDefinitions.createCoordinateSystem(StandardDefinitions.ELLIPSOIDAL_3D, true); } - synchronized (this) { - object = cachedGeo3D; - if (object == null) { - if (cs == null) { - cs = (EllipsoidalCS) StandardDefinitions.createCoordinateSystem(StandardDefinitions.ELLIPSOIDAL_3D, true); - } - // Use same name and datum than the geographic CRS. - object = new DefaultGeographicCRS(properties(base, geo3D), base.getDatum(), base.getDatumEnsemble(), cs); - cachedGeo3D = object; - } - } + // Use same name and datum than the geographic CRS. + cachedGeo3D = new DefaultGeographicCRS(properties(base, geo3D), base.getDatum(), base.getDatumEnsemble(), cs); } - return object; + return cachedGeo3D; } /** @@ -761,15 +744,12 @@ public enum CommonCRS { * @see CRS#forCode(String) * @see DefaultGeocentricCRS */ - public GeodeticCRS geocentric() { - GeodeticCRS object = cachedGeocentric; - if (object == null) { + public synchronized GeodeticCRS geocentric() { + if (cachedGeocentric == null) { if (geocentric != 0) { final GeodeticAuthorityFactory factory = factory(); if (factory != null) try { - // Synchronization provided by the cache of the factory. - cachedGeocentric = object = factory.createGeodeticCRS(String.valueOf(geocentric)); - return object; + return cachedGeocentric = factory.createGeodeticCRS(String.valueOf(geocentric)); } catch (FactoryException e) { failure(this, "geocentric", e, geocentric); } @@ -781,22 +761,15 @@ public enum CommonCRS { * We will arbitrarily create this CS only for the most frequently created CRS, * and share that CS instance for all other constants. */ - CartesianCS cs = null; + final CartesianCS cs; if (this != DEFAULT) { cs = (CartesianCS) DEFAULT.geocentric().getCoordinateSystem(); + } else { + cs = (CartesianCS) StandardDefinitions.createCoordinateSystem(StandardDefinitions.EARTH_CENTRED, true); } - synchronized (this) { - object = cachedGeocentric; - if (object == null) { - if (cs == null) { - cs = (CartesianCS) StandardDefinitions.createCoordinateSystem(StandardDefinitions.EARTH_CENTRED, true); - } - object = new DefaultGeocentricCRS(properties(base, geocentric), base.getDatum(), base.getDatumEnsemble(), cs); - cachedGeocentric = object; - } - } + cachedGeocentric = new DefaultGeocentricCRS(properties(base, geocentric), base.getDatum(), base.getDatumEnsemble(), cs); } - return object; + return cachedGeocentric; } /** @@ -814,9 +787,8 @@ public enum CommonCRS { * * @since 0.7 */ - public GeodeticCRS spherical() { - GeodeticCRS object = cachedSpherical; - if (object == null) { + public synchronized GeodeticCRS spherical() { + if (cachedSpherical == null) { /* * All constants defined in this enumeration use the same coordinate system, EPSG:6404. * We will arbitrarily create this CS only for the most frequently created CRS, @@ -828,29 +800,22 @@ public enum CommonCRS { } else { final GeodeticAuthorityFactory factory = factory(); if (factory != null) try { - // Synchronization provided by the cache of the factory. cs = factory.createSphericalCS(Short.toString(StandardDefinitions.SPHERICAL)); } catch (FactoryException e) { failure(this, "spherical", e, StandardDefinitions.SPHERICAL); } + if (cs == null) { + cs = (SphericalCS) StandardDefinitions.createCoordinateSystem(StandardDefinitions.SPHERICAL, true); + } } // Use same name and datum than the geographic CRS. final GeographicCRS base = geographic(); - synchronized (this) { - object = cachedSpherical; - if (object == null) { - if (cs == null) { - cs = (SphericalCS) StandardDefinitions.createCoordinateSystem(StandardDefinitions.SPHERICAL, true); - } - object = new DefaultGeocentricCRS(IdentifiedObjects.getProperties(base, exclude()), - base.getDatum(), - base.getDatumEnsemble(), - cs); - cachedSpherical = object; - } - } + cachedSpherical = new DefaultGeocentricCRS(IdentifiedObjects.getProperties(base, exclude()), + base.getDatum(), + base.getDatumEnsemble(), + cs); } - return object; + return cachedSpherical; } /** @@ -876,12 +841,11 @@ public enum CommonCRS { * @see #forDatum(CoordinateReferenceSystem) * @see org.apache.sis.referencing.datum.DefaultGeodeticDatum */ - public GeodeticDatum datum() { + public synchronized GeodeticDatum datum() { GeodeticDatum object = datum(cached); if (object == null) { final GeodeticAuthorityFactory factory = factory(); if (factory != null) try { - // Synchronization provided by the cache of the factory. cached = object = factory.createGeodeticDatum(String.valueOf(datum)); return object; } catch (FactoryException e) { @@ -889,13 +853,7 @@ public enum CommonCRS { } final var ei = ellipsoid(); final var pm = primeMeridian(); - synchronized (this) { - object = datum(cached); - if (object == null) { - object = StandardDefinitions.createGeodeticDatum(datum, ei, pm); - cached = object; - } - } + cached = object = StandardDefinitions.createGeodeticDatum(datum, ei, pm); } return object; } @@ -931,28 +889,22 @@ public enum CommonCRS { * * @see org.apache.sis.referencing.datum.DefaultEllipsoid */ - public Ellipsoid ellipsoid() { + public synchronized Ellipsoid ellipsoid() { Ellipsoid object = ellipsoid(cached); if (object == null) { if (this == NAD83) { - cached = object = ETRS89.ellipsoid(); // Share the same instance for NAD83 and ETRS89. - return object; - } - final GeodeticAuthorityFactory factory = factory(); - if (factory != null) try { - // Synchronization provided by the cache of the factory. - cached = object = factory.createEllipsoid(String.valueOf(ellipsoid)); - return object; - } catch (FactoryException e) { - failure(this, "ellipsoid", e, ellipsoid); - } - synchronized (this) { - object = ellipsoid(cached); - if (object == null) { - object = StandardDefinitions.createEllipsoid(ellipsoid); - cached = object; + object = ETRS89.ellipsoid(); // Share the same instance for NAD83 and ETRS89. + } else { + final GeodeticAuthorityFactory factory = factory(); + if (factory != null) try { + cached = object = factory.createEllipsoid(String.valueOf(ellipsoid)); + return object; + } catch (FactoryException e) { + failure(this, "ellipsoid", e, ellipsoid); } + object = StandardDefinitions.createEllipsoid(ellipsoid); } + cached = object; } return object; } @@ -972,28 +924,22 @@ public enum CommonCRS { * * @see org.apache.sis.referencing.datum.DefaultPrimeMeridian */ - public PrimeMeridian primeMeridian() { + public synchronized PrimeMeridian primeMeridian() { PrimeMeridian object = primeMeridian(cached); if (object == null) { if (this != DEFAULT) { - cached = object = DEFAULT.primeMeridian(); // Share the same instance for all constants. - return object; - } - final GeodeticAuthorityFactory factory = factory(); - if (factory != null) try { - // Synchronization provided by the cache of the factory. - cached = object = factory.createPrimeMeridian(StandardDefinitions.GREENWICH); - return object; - } catch (FactoryException e) { - failure(this, "primeMeridian", e, Constants.EPSG_GREENWICH); - } - synchronized (this) { - object = primeMeridian(cached); - if (object == null) { - object = StandardDefinitions.primeMeridian(); - cached = object; + object = DEFAULT.primeMeridian(); // Share the same instance for all constants. + } else { + final GeodeticAuthorityFactory factory = factory(); + if (factory != null) try { + cached = object = factory.createPrimeMeridian(StandardDefinitions.GREENWICH); + return object; + } catch (FactoryException e) { + failure(this, "primeMeridian", e, Constants.EPSG_GREENWICH); } + object = StandardDefinitions.primeMeridian(); } + cached = object; } return object; } @@ -1366,7 +1312,7 @@ public enum CommonCRS { * on which method has been invoked. The kind of object stored in this field may change during the * application execution. */ - private transient volatile IdentifiedObject cached; + private transient IdentifiedObject cached; /** * Creates a new enumeration value of the given name. @@ -1420,31 +1366,25 @@ public enum CommonCRS { * * @see DefaultVerticalCRS */ - public VerticalCRS crs() { + public synchronized VerticalCRS crs() { VerticalCRS object = crs(cached); if (object == null) { if (isEPSG) { final GeodeticAuthorityFactory factory = factory(); if (factory != null) try { - // Synchronization provided by the cache of the factory. cached = object = factory.createVerticalCRS(String.valueOf(crs)); return object; } catch (FactoryException e) { failure(this, "crs", e, crs); } } - synchronized (this) { - object = crs(cached); - if (object == null) { - if (isEPSG) { - object = StandardDefinitions.createVerticalCRS(crs, datum()); - } else { - final VerticalCS cs = cs(); - object = new DefaultVerticalCRS(IdentifiedObjects.getProperties(cs, exclude()), datum(), null, cs); - } - cached = object; - } + if (isEPSG) { + object = StandardDefinitions.createVerticalCRS(crs, datum()); + } else { + final VerticalCS cs = cs(); + object = new DefaultVerticalCRS(IdentifiedObjects.getProperties(cs, exclude()), datum(), null, cs); } + cached = object; } return object; } @@ -1488,39 +1428,33 @@ public enum CommonCRS { * * @see DefaultVerticalDatum */ - public VerticalDatum datum() { + public synchronized VerticalDatum datum() { VerticalDatum object = datum(cached); if (object == null) { if (isEPSG) { final GeodeticAuthorityFactory factory = factory(); if (factory != null) try { - // Synchronization provided by the cache of the factory. cached = object = factory.createVerticalDatum(String.valueOf(datum)); return object; } catch (FactoryException e) { failure(this, "datum", e, datum); } } - synchronized (this) { - object = datum(cached); - if (object == null) { - if (isEPSG) { - object = StandardDefinitions.createVerticalDatum(datum); - } else { - /* - * All cases where the first constructor argument is `false`, currently BAROMETRIC and - * ELLIPSOIDAL. The way to construct the ellipsoidal pseudo-method shall be equivalent - * to a call to `VerticalDatumTypes.ellipsoidal()`. - */ - RealizationMethod method = null; - if (this != OTHER_SURFACE) { - method = RealizationMethod.valueOf(name()); - } - object = new DefaultVerticalDatum(properties(datum), method); - } - cached = object; + if (isEPSG) { + object = StandardDefinitions.createVerticalDatum(datum); + } else { + /* + * All cases where the first constructor argument is `false`, currently BAROMETRIC and + * ELLIPSOIDAL. The way to construct the ellipsoidal pseudo-method shall be equivalent + * to a call to `VerticalDatumTypes.ellipsoidal()`. + */ + RealizationMethod method = null; + if (this != OTHER_SURFACE) { + method = RealizationMethod.valueOf(name()); } + object = new DefaultVerticalDatum(properties(datum), method); } + cached = object; } return object; } @@ -1691,7 +1625,7 @@ public enum CommonCRS { * on which method has been invoked. The kind of object stored in this field may change during the * application execution. */ - private transient volatile IdentifiedObject cached; + private transient IdentifiedObject cached; /** * Creates a new enumeration value of the given name with time counted since the given epoch. @@ -1796,26 +1730,20 @@ public enum CommonCRS { * * @see DefaultTemporalCRS */ - public TemporalCRS crs() { + public synchronized TemporalCRS crs() { TemporalCRS object = crs(cached); if (object == null) { - synchronized (this) { - object = crs(cached); - if (object == null) { - final TemporalDatum datum = datum(); - final Map<String,?> source; - if (this == JAVA) { - source = properties(Vocabulary.formatInternational(key, "Java")); - } else { - source = IdentifiedObjects.getProperties(datum, exclude()); - } - final Map<String,Object> properties = new HashMap<>(source); - properties.put(TemporalCRS.IDENTIFIERS_KEY, - new NamedIdentifier(isOGC ? Citations.OGC : Citations.SIS, identifier)); - object = new DefaultTemporalCRS(properties, datum, null, cs()); - cached = object; - } + final TemporalDatum datum = datum(); + final Map<String,?> source; + if (this == JAVA) { + source = properties(Vocabulary.formatInternational(key, "Java")); + } else { + source = IdentifiedObjects.getProperties(datum, exclude()); } + final Map<String,Object> properties = new HashMap<>(source); + properties.put(TemporalCRS.IDENTIFIERS_KEY, + new NamedIdentifier(isOGC ? Citations.OGC : Citations.SIS, identifier)); + cached = object = new DefaultTemporalCRS(properties, datum, null, cs()); } return object; } @@ -1868,26 +1796,20 @@ public enum CommonCRS { * * @see DefaultTemporalDatum */ - public TemporalDatum datum() { + public synchronized TemporalDatum datum() { TemporalDatum object = datum(cached); if (object == null) { if (this == UNIX) { cached = object = JAVA.datum(); // Share the same instance for UNIX and JAVA. return object; } - synchronized (this) { - object = datum(cached); - if (object == null) { - final Map<String,?> properties; - if (key == Vocabulary.Keys.Time_1) { - properties = properties(Vocabulary.formatInternational(key, "Unix/POSIX")); - } else { - properties = properties(key); - } - object = new DefaultTemporalDatum(properties, Instant.ofEpochSecond(epoch)); - cached = object; - } + final Map<String,?> properties; + if (key == Vocabulary.Keys.Time_1) { + properties = properties(Vocabulary.formatInternational(key, "Unix/POSIX")); + } else { + properties = properties(key); } + cached = object = new DefaultTemporalDatum(properties, Instant.ofEpochSecond(epoch)); } return object; } @@ -2152,11 +2074,25 @@ public enum CommonCRS { * After invoking this method, the caller will fallback on hard-coded values. */ private static void failure(final Object caller, final String method, final FactoryException e, final int code) { + final LogRecord record; String message = Resources.format(Resources.Keys.CanNotInstantiateGeodeticObject_1, (Constants.EPSG + ':') + code); - message = Exceptions.formatChainedMessages(null, message, e); - final var record = new LogRecord(Level.WARNING, message); - if (!(e instanceof UnavailableFactoryException && AuthorityFactories.isUnavailable((UnavailableFactoryException) e))) { + if (e instanceof UnavailableFactoryException && !AuthorityFactories.isUnavailable((UnavailableFactoryException) e)) { + /* + * This exception may be normal if the user didn't installed the EPSG geodetic dataset. + * However, we use the `WARNING` level anyway because this exception happens only when + * user specified some from of data source, e.g with the SIS_DATA environment variable, + * in which case she may want to know that it didn't worked. This exception should not + * occur when the user did not configured anything. + * + * This exception usually happens only once, because the failure should be recorded in the + * `AuthorityFactories.EPSG` field. This exception may nevertheless happen more than once + * if there is a race condition (many calls to `CommonCRS` in different threads before the + * failure get recorded). It happens during tests. + */ + record = new LogRecord(Level.WARNING, Exceptions.formatChainedMessages(null, message, e)); + } else { // Append the stack trace only if the exception is for a reason different than unavailable factory. + record = new LogRecord(Level.WARNING, message); record.setThrown(e); } Logging.completeAndLog(AuthorityFactories.LOGGER, caller.getClass(), method, record); diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java index cb507103ed..95dd062d1c 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java @@ -752,7 +752,7 @@ public abstract class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFa * Do not log the stack trace if we failed because of UnavailableFactoryException since it may be * normal (the EPSG geodetic dataset is optional, even if strongly recommended). */ - final LogRecord record = new LogRecord(c == null ? Level.WARNING : Level.FINE, e.getLocalizedMessage()); + final var record = new LogRecord(c == null ? Level.WARNING : Level.FINE, e.getLocalizedMessage()); if (!(e instanceof UnavailableFactoryException)) { record.setThrown(e); } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java index 4f179926bf..035277476d 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java @@ -583,12 +583,14 @@ public class IdentifiedObjectFinder { * Invoked when an exception occurred during the creation of a candidate from a code. */ private static void exceptionOccurred(final FactoryException exception) { - /* - * use `getMessage()` instead of `getLocalizedMessage()` for - * giving preference to the locale of system administrator. - */ - Logging.completeAndLog(GeodeticAuthorityFactory.LOGGER, IdentifiedObjectFinder.class, - "find", new LogRecord(Level.FINER, exception.getMessage())); + if (GeodeticAuthorityFactory.LOGGER.isLoggable(Level.FINER)) { + /* + * use `getMessage()` instead of `getLocalizedMessage()` for + * giving preference to the locale of system administrator. + */ + Logging.completeAndLog(GeodeticAuthorityFactory.LOGGER, IdentifiedObjectFinder.class, + "find", new LogRecord(Level.FINER, exception.getMessage())); + } } /** diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGFactory.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGFactory.java index 244b0bf26b..50fb583cb1 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGFactory.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGFactory.java @@ -246,10 +246,10 @@ public class EPSGFactory extends ConcurrentAuthorityFactory<EPSGDataAccess> impl * or {@code null} for the default values. * @throws ClassCastException if a property value is not of the expected class. * @throws IllegalArgumentException if a property value is invalid. - * @throws FactoryException if an error occurred while creating the EPSG factory. + * @throws UnavailableFactoryException if an error occurred while creating the EPSG factory. */ @SuppressWarnings("this-escape") // The invoked method does not store `this` and is not overrideable. - public EPSGFactory(Map<String,?> properties) throws FactoryException { + public EPSGFactory(Map<String,?> properties) throws UnavailableFactoryException { super(EPSGDataAccess.class); if (properties == null) { properties = Map.of(); @@ -266,12 +266,13 @@ public class EPSGFactory extends ConcurrentAuthorityFactory<EPSGDataAccess> impl this.locale = locale; if (ds == null) try { ds = Initializer.getDataSource(); - if (ds == null) { - throw new UnavailableFactoryException(String.valueOf(Initializer.unspecified(locale, false))); - } } catch (Exception e) { throw new UnavailableFactoryException(canNotUse(e), e); } + if (ds == null) { + // Must be outside the above `try` block. + throw new UnavailableFactoryException(String.valueOf(Initializer.unspecified(locale, false))); + } final var c = new ReferencingFactoryContainer(properties); dataSource = ds; nameFactory = c.getNameFactory(); @@ -406,7 +407,7 @@ public class EPSGFactory extends ConcurrentAuthorityFactory<EPSGDataAccess> impl } } } catch (IOException | SQLException e) { - message = installer.failure(locale, e); + message = installer.failure(locale); failure = e; } } catch (SQLException e) { @@ -418,7 +419,7 @@ public class EPSGFactory extends ConcurrentAuthorityFactory<EPSGDataAccess> impl * Derby sometimes wraps SQLException into another SQLException. For making the stack strace a * little bit simpler, keep only the root cause provided that the exception type is compatible. */ - UnavailableFactoryException exception = new UnavailableFactoryException(message, Exceptions.unwrap(failure)); + var exception = new UnavailableFactoryException(message, Exceptions.unwrap(failure)); exception.setUnavailableFactory(this); throw exception; } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGInstaller.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGInstaller.java index dfd4171ba0..23f169f240 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGInstaller.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGInstaller.java @@ -27,7 +27,6 @@ import java.sql.SQLException; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import org.apache.sis.util.StringBuilders; -import org.apache.sis.util.Exceptions; import org.apache.sis.metadata.sql.privy.ScriptRunner; import org.apache.sis.metadata.sql.privy.SQLUtilities; import org.apache.sis.util.privy.Constants; @@ -297,12 +296,12 @@ final class EPSGInstaller extends ScriptRunner { * caught an exception. This method completes the exception message with the file name and line number where the * error occurred, if such information is available. */ - final String failure(final Locale locale, final Exception cause) { + final String failure(final Locale locale) { String message = Messages.forLocale(locale).getString(Messages.Keys.CanNotCreateSchema_1, EPSG); String status = status(locale); if (status != null) { message = message + ' ' + status; } - return Exceptions.formatChainedMessages(locale, message, cause); + return message; } } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ServicesForMetadata.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ServicesForMetadata.java index 7c6eb1fd3a..9ff0ed9f21 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ServicesForMetadata.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ServicesForMetadata.java @@ -62,6 +62,7 @@ import org.apache.sis.metadata.privy.ReferencingServices; import org.apache.sis.measure.Latitude; import org.apache.sis.measure.Longitude; import org.apache.sis.system.Modules; +import org.apache.sis.util.Classes; import org.apache.sis.util.Exceptions; import org.apache.sis.util.Utilities; import org.apache.sis.util.privy.Constants; @@ -504,7 +505,7 @@ public final class ServicesForMetadata extends ReferencingServices { authority = CRS.getAuthorityFactory(Constants.EPSG).getAuthority(); } catch (FactoryException e) { final String msg = Exceptions.getLocalizedMessage(e, locale); - return (msg != null) ? msg : e.toString(); + return (msg != null) ? msg : Classes.getShortClassName(e); } if (authority != null) { final OnLineFunction f = OnLineFunction.valueOf(CONNECTION); diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/ProjectedTransformTry.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/ProjectedTransformTry.java index 7ead80c4f7..cfe429ed60 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/ProjectedTransformTry.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/ProjectedTransformTry.java @@ -26,6 +26,7 @@ import java.text.NumberFormat; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; import org.apache.sis.io.TableAppender; +import org.apache.sis.util.Classes; import org.apache.sis.util.ArraysExt; import org.apache.sis.util.Exceptions; import org.apache.sis.util.resources.Errors; @@ -435,7 +436,7 @@ final class ProjectedTransformTry implements Comparable<ProjectedTransformTry>, if (error != null) { message = Exceptions.getLocalizedMessage(error, locale); if (message == null) { - message = error.getClass().getSimpleName(); + message = Classes.getShortClassName(error); } } else if (correlation > 0) { if (nf == null) { diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/geometry/DirectPosition1DTest.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/geometry/DirectPosition1DTest.java index 22b38cc339..cf0ae605dd 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/geometry/DirectPosition1DTest.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/geometry/DirectPosition1DTest.java @@ -43,7 +43,7 @@ public final class DirectPosition1DTest extends TestCase { */ @Test public void testWktFormatting() { - final DirectPosition1D position = new DirectPosition1D(8.5); + final var position = new DirectPosition1D(8.5); assertEquals("POINT(8.5)", position.toString()); validate(position); } @@ -53,7 +53,7 @@ public final class DirectPosition1DTest extends TestCase { */ @Test public void testWktParsing() { - final DirectPosition1D position = new DirectPosition1D("POINT(8)"); + final var position = new DirectPosition1D("POINT(8)"); assertEquals("POINT(8)", position.toString()); validate(position); } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/IOUtilities.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/IOUtilities.java index 891c536b1c..3dd75cd7ed 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/IOUtilities.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/IOUtilities.java @@ -46,7 +46,6 @@ import javax.imageio.stream.ImageInputStream; import javax.xml.stream.Location; import javax.xml.stream.XMLStreamReader; import org.apache.sis.util.CharSequences; -import org.apache.sis.util.Exceptions; import org.apache.sis.util.Static; import org.apache.sis.util.resources.Errors; import org.apache.sis.util.privy.Constants; @@ -415,8 +414,8 @@ public final class IOUtilities extends Static { } catch (MalformedURLException cause) { ex = cause; } catch (IllegalArgumentException | URISyntaxException cause) { - ex = (MalformedURLException) new MalformedURLException(Exceptions.formatChainedMessages(null, - Errors.format(Errors.Keys.IllegalArgumentValue_2, "path", path), cause)).initCause(cause); + ex = new MalformedURLException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "path", path)); + ex.initCause(cause); } if (suppressed != null) { ex.addSuppressed(suppressed); diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/event/StoreListeners.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/event/StoreListeners.java index 9e57f77cd6..01d7a950c3 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/event/StoreListeners.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/event/StoreListeners.java @@ -482,14 +482,16 @@ public class StoreListeners implements Localized { if (exception == null) { ArgumentChecks.ensureNonEmpty("message", message); } else { - message = Exceptions.formatChainedMessages(getLocale(), message, exception); if (message == null) { - message = exception.toString(); + message = Exceptions.getLocalizedMessage(exception, getLocale()); + if (message == null) { + message = Classes.getShortClassName(exception); + } } } - final LogRecord record = new LogRecord(level, message); + final var record = new LogRecord(level, message); if (exception == null) { - StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk((stream) -> stream.filter( + StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk((stream) -> stream.filter( (frame) -> setPublicSource(record, frame.getDeclaringClass(), frame.getMethodName())).findFirst()); } else try { record.setThrown(exception); diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/system/DataDirectory.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/system/DataDirectory.java index b38f5c23a1..ce5d59171b 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/system/DataDirectory.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/system/DataDirectory.java @@ -116,7 +116,8 @@ public enum DataDirectory { private static void warning(final Exception e, final short key, final Object... parameters) { if (key != lastWarning) { lastWarning = key; - log(Level.WARNING, e, key, parameters); + boolean config = (key == Messages.Keys.DataDirectoryNotSpecified_1); + log(config ? Level.CONFIG : Level.WARNING, e, key, parameters); } } diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Exceptions.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Exceptions.java index fed0584a07..fd71139c3a 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Exceptions.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Exceptions.java @@ -111,16 +111,22 @@ public final class Exceptions extends Static { } /** - * Returns a string which contains the given message on the first line, followed by the - * {@linkplain #getLocalizedMessage(Throwable, Locale) localized message} of the given exception - * on the next line. If the exception has a {@linkplain Throwable#getCause() causes}, then - * the class name and the localized message of the cause are formatted on the next line - * and the process is repeated for the whole cause chain, omitting duplicated messages. + * Returns a string which contains the given message on the first line, + * followed by the localized message of the given exception on the next line. + * If the exception has a {@linkplain Throwable#getCause() causes}, then the class name and the + * {@linkplain #getLocalizedMessage(Throwable, Locale) localized message} of the cause are formatted + * on the next line. The process is repeated for the whole cause chain, omitting duplicated messages. + * This method does not format the stack trace. * - * <p>{@link SQLException} is handled especially in order to process the - * {@linkplain SQLException#getNextException() next exception} instead of the cause.</p> + * <h4>Special cases</h4> + * {@link SQLException} is handled is a special way by giving precedence to + * {@link SQLException#getNextException()} over {@link Throwable#getCause()}. * - * <p>This method does not format the stack trace.</p> + * <h4>When to use</h4> + * This method should not be used when the given exception will be reported through, for example, + * {@link Throwable#initCause(Throwable)} or {@link java.util.logging.LogRecord#setThrown(Throwable)}, + * because the redundancy may be confusing. This method is rather for situations where the exception + * will be discarded or hidden. * * @param locale the preferred locale for the exception message, or {@code null}. * @param header the message to insert on the first line, or {@code null} if none. @@ -129,7 +135,7 @@ public final class Exceptions extends Static { * and no exception provide a message. */ public static String formatChainedMessages(final Locale locale, final String header, Throwable cause) { - final List<String> previousLines = new ArrayList<>(); + final var previousLines = new ArrayList<String>(); StringBuilder buffer = null; Vocabulary resources = null; while (cause != null) { diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/logging/Logging.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/logging/Logging.java index c3c68deafd..3387642587 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/logging/Logging.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/logging/Logging.java @@ -275,10 +275,12 @@ public final class Logging extends Static { buffer.append(": ").append(message); } message = buffer.toString(); - message = Exceptions.formatChainedMessages(null, message, error); - final LogRecord record = new LogRecord(level, message); + final LogRecord record; if (level.intValue() >= LEVEL_THRESHOLD_FOR_STACKTRACE) { + record = new LogRecord(level, message); record.setThrown(error); + } else { + record = new LogRecord(level, Exceptions.formatChainedMessages(null, message, error)); } if (logger == null || classe == null || method == null) { logger = inferCaller(logger, classe, method, Arrays.stream(error.getStackTrace()), record); diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/IndexedResourceBundle.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/IndexedResourceBundle.java index 5ae36d1d3d..71eda54802 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/IndexedResourceBundle.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/IndexedResourceBundle.java @@ -321,15 +321,17 @@ public abstract class IndexedResourceBundle extends ResourceBundle implements Lo * different Java implementation, but it doesn't matter here since * we use the result only for logging purpose. */ - String language = null; - if (locale != null) { - language = locale.getDisplayName(Locale.US); - } - if (Strings.isNullOrEmpty(language)) { - language = "<root>"; + if (LOGGER.isLoggable(record.getLevel())) { + String language = null; + if (locale != null) { + language = locale.getDisplayName(Locale.US); + } + if (Strings.isNullOrEmpty(language)) { + language = "<root>"; + } + record.setParameters(new String[] {language, baseName}); + Logging.completeAndLog(LOGGER, IndexedResourceBundle.class, methodName, record); } - record.setParameters(new String[] {language, baseName}); - Logging.completeAndLog(LOGGER, IndexedResourceBundle.class, methodName, record); } this.values = values; } diff --git a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/Assertions.java b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/Assertions.java index aeeec8c5ff..dd883066f4 100644 --- a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/Assertions.java +++ b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/Assertions.java @@ -35,7 +35,6 @@ import java.io.ByteArrayOutputStream; import org.apache.sis.util.Utilities; import org.apache.sis.util.CharSequences; import org.apache.sis.util.ComparisonMode; -import org.apache.sis.util.Exceptions; import org.apache.sis.util.Classes; import org.apache.sis.util.Static; @@ -119,8 +118,8 @@ public final class Assertions extends Static { for (int i=0; i<length; i++) try { assertEqualsIgnoreMetadata(expected[i], actual[i]); } catch (AssertionError e) { - throw new AssertionError(Exceptions.formatChainedMessages(null, "Comparison failure at index " - + i + " (a " + Classes.getShortClassName(actual[i]) + ").", e), e); + throw new AssertionError("Comparison failure at index " + i + + " (a " + Classes.getShortClassName(actual[i]) + "): " + e, e); } assertEquals(expected.length, actual.length, "Unexpected array length."); } diff --git a/incubator/src/org.apache.sis.storage.gsf/main/org/apache/sis/storage/gsf/panama/LibraryLoader.java b/incubator/src/org.apache.sis.storage.gsf/main/org/apache/sis/storage/gsf/panama/LibraryLoader.java index b42ebfeaaa..1ed6263ae5 100644 --- a/incubator/src/org.apache.sis.storage.gsf/main/org/apache/sis/storage/gsf/panama/LibraryLoader.java +++ b/incubator/src/org.apache.sis.storage.gsf/main/org/apache/sis/storage/gsf/panama/LibraryLoader.java @@ -26,7 +26,6 @@ import java.lang.foreign.SymbolLookup; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.gsf.GSF; import org.apache.sis.system.Shutdown; -import org.apache.sis.util.Exceptions; /** @@ -117,8 +116,7 @@ public final class LibraryLoader { if (error == null) { return Optional.empty(); } - String msg = "Cannot initialize the GSF library."; - var record = new LogRecord(Level.CONFIG, Exceptions.formatChainedMessages(null, msg, error)); + var record = new LogRecord(Level.CONFIG, "Cannot initialize the GSF library."); record.setThrown(error); return Optional.of(record); } diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/AuthorityCodes.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/AuthorityCodes.java index 78301442fd..3eec66232c 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/AuthorityCodes.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/AuthorityCodes.java @@ -36,6 +36,7 @@ import org.opengis.util.FactoryException; import org.opengis.referencing.IdentifiedObject; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.CRSAuthorityFactory; +import org.apache.sis.util.Classes; import org.apache.sis.util.Exceptions; import org.apache.sis.util.iso.Types; import org.apache.sis.util.logging.Logging; @@ -481,7 +482,7 @@ final class AuthorityCodes extends ObservableListBase<Code> final Code code = new Code(Vocabulary.forLocale(locale).getString(Vocabulary.Keys.Errors)); String message = Exceptions.getLocalizedMessage(e, locale); if (message == null) { - message = e.getClass().getSimpleName(); + message = Classes.getShortClassName(e); } code.name().set(message); add(code); diff --git a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/LibraryLoader.java b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/LibraryLoader.java index f1b949b3a2..b9c6aa63b8 100644 --- a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/LibraryLoader.java +++ b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/LibraryLoader.java @@ -27,7 +27,6 @@ import java.lang.foreign.Arena; import java.lang.foreign.SymbolLookup; import org.apache.sis.storage.DataStoreException; import org.apache.sis.system.Shutdown; -import org.apache.sis.util.Exceptions; /** @@ -215,8 +214,7 @@ create: try { if (error == null) { return Optional.empty(); } - String msg = "Cannot initialize the " + name + " library."; - var record = new LogRecord(Level.CONFIG, Exceptions.formatChainedMessages(null, msg, error)); + LogRecord record = Resources.forLocale(null).getLogRecord(Level.CONFIG, Resources.Keys.CannotInitialize_1, name); record.setThrown(error); return Optional.of(record); } diff --git a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/Resources.java b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/Resources.java index 1ba4bde055..96732637d5 100644 --- a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/Resources.java +++ b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/Resources.java @@ -59,7 +59,7 @@ public class Resources extends IndexedResourceBundle { public static final short AllowedDrivers_1 = 1; /** - * Cannot initialize {0}. + * Cannot initialize the {0} native library. */ public static final short CannotInitialize_1 = 2; diff --git a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/Resources.properties b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/Resources.properties index 44d88c2730..77900aec2f 100644 --- a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/Resources.properties +++ b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/Resources.properties @@ -20,7 +20,7 @@ # For resources shared by all modules in the Apache SIS project, see "org.apache.sis.util.resources" package. # AllowedDrivers_1 = Allowed {0} drivers for opening the file. -CannotInitialize_1 = Cannot initialize {0}. +CannotInitialize_1 = Cannot initialize the {0} native library. FatalLibraryError_1 = A fatal error occurred and {0} should not be used anymore in this JVM. FunctionNotFound_1 = A function of the {0} library has not been found. LibraryNotFound_1 = The {0} library has not been found. diff --git a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/Resources_fr.properties b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/Resources_fr.properties index dbaf05b743..f3173c097a 100644 --- a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/Resources_fr.properties +++ b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/panama/Resources_fr.properties @@ -25,7 +25,7 @@ # U+00A0 NO-BREAK SPACE before : # AllowedDrivers_1 = Pilotes {0} autoris\u00e9s pour ouvrir le fichier. -CannotInitialize_1 = Ne peut pas initialiser {0}. +CannotInitialize_1 = Ne peut pas initialiser la biblioth\u00e8que native {0}. FatalLibraryError_1 = Une erreur fatale s\u2019est produite et la biblioth\u00e8que {0} ne devrait plus \u00eatre utilis\u00e9e dans cette JVM. FunctionNotFound_1 = Une fonction de la biblioth\u00e8que {0} n\u2019a pas \u00e9t\u00e9 trouv\u00e9e. LibraryNotFound_1 = La biblioth\u00e8que {0} n\u2019a pas \u00e9t\u00e9 trouv\u00e9e.