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 5e6524b6d6a26bd42daf96473e1bab66a0fafea4 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Mon Feb 19 16:27:28 2024 +0100 Reduce the risk of deadlock in `CommonCRS` methods by reducing the size of synchronized blocks. --- .../main/org/apache/sis/referencing/CommonCRS.java | 281 +++++++++++---------- 1 file changed, 150 insertions(+), 131 deletions(-) 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 9a817a46c5..7d2a1521b5 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 @@ -629,28 +629,31 @@ public enum CommonCRS { public 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) { + failure(this, "geographic", e, geographic); + } + final GeodeticDatum frame = datum(); + /* + * All constants defined in this enumeration use the same coordinate system, EPSG:6422. + * 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; + if (this != DEFAULT) { + cs = DEFAULT.geographic().getCoordinateSystem(); + } synchronized (this) { object = geographic(cached); if (object == null) { - final GeodeticAuthorityFactory factory = factory(); - if (factory != null) try { - cached = object = factory.createGeographicCRS(String.valueOf(geographic)); - return object; - } catch (FactoryException e) { - failure(this, "geographic", e, geographic); - } - /* - * All constants defined in this enumeration use the same coordinate system, EPSG:6422. - * We will arbitrarily create this CS only for the most frequently created CRS, - * and share that CS instance for all other constants. - */ - final EllipsoidalCS cs; - if (this == DEFAULT) { + if (cs == null) { cs = (EllipsoidalCS) StandardDefinitions.createCoordinateSystem(StandardDefinitions.ELLIPSOIDAL_2D, true); - } else { - cs = DEFAULT.geographic().getCoordinateSystem(); } - object = StandardDefinitions.createGeographicCRS(geographic, datum(), cs); + object = StandardDefinitions.createGeographicCRS(geographic, frame, cs); cached = object; } } @@ -685,31 +688,33 @@ public enum CommonCRS { public GeographicCRS geographic3D() { GeographicCRS object = cachedGeo3D; if (object == 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; + } catch (FactoryException e) { + failure(this, "geographic3D", e, geo3D); + } + } + final GeographicCRS base = geographic(); + /* + * All constants defined in this enumeration use the same coordinate system, EPSG:6423. + * 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; + if (this != DEFAULT) { + cs = DEFAULT.geographic3D().getCoordinateSystem(); + } synchronized (this) { object = cachedGeo3D; if (object == null) { - if (geo3D != 0) { - final GeodeticAuthorityFactory factory = factory(); - if (factory != null) try { - cachedGeo3D = object = factory.createGeographicCRS(String.valueOf(geo3D)); - return object; - } catch (FactoryException e) { - failure(this, "geographic3D", e, geo3D); - } - } - /* - * All constants defined in this enumeration use the same coordinate system, EPSG:6423. - * We will arbitrarily create this CS only for the most frequently created CRS, - * and share that CS instance for all other constants. - */ - final EllipsoidalCS cs; - if (this == DEFAULT) { + if (cs == null) { cs = (EllipsoidalCS) StandardDefinitions.createCoordinateSystem(StandardDefinitions.ELLIPSOIDAL_3D, true); - } else { - cs = DEFAULT.geographic3D().getCoordinateSystem(); } // Use same name and datum than the geographic CRS. - final GeographicCRS base = geographic(); object = new DefaultGeographicCRS(properties(base, geo3D), base.getDatum(), cs); cachedGeo3D = object; } @@ -744,31 +749,33 @@ public enum CommonCRS { public GeocentricCRS geocentric() { GeocentricCRS object = cachedGeocentric; if (object == null) { + if (geocentric != 0) { + final GeodeticAuthorityFactory factory = factory(); + if (factory != null) try { + // Synchronization provided by the cache of the factory. + cachedGeocentric = object = factory.createGeocentricCRS(String.valueOf(geocentric)); + return object; + } catch (FactoryException e) { + failure(this, "geocentric", e, geocentric); + } + } + // Use same name and datum than the geographic CRS. + final GeographicCRS base = geographic(); + /* + * All constants defined in this enumeration use the same coordinate system, EPSG:6500. + * 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; + if (this != DEFAULT) { + cs = (CartesianCS) DEFAULT.geocentric().getCoordinateSystem(); + } synchronized (this) { object = cachedGeocentric; if (object == null) { - if (geocentric != 0) { - final GeodeticAuthorityFactory factory = factory(); - if (factory != null) try { - cachedGeocentric = object = factory.createGeocentricCRS(String.valueOf(geocentric)); - return object; - } catch (FactoryException e) { - failure(this, "geocentric", e, geocentric); - } - } - /* - * All constants defined in this enumeration use the same coordinate system, EPSG:6500. - * We will arbitrarily create this CS only for the most frequently created CRS, - * and share that CS instance for all other constants. - */ - final CartesianCS cs; - if (this == DEFAULT) { + if (cs == null) { cs = (CartesianCS) StandardDefinitions.createCoordinateSystem(StandardDefinitions.EARTH_CENTRED, true); - } else { - cs = (CartesianCS) DEFAULT.geocentric().getCoordinateSystem(); } - // Use same name and datum than the geographic CRS. - final GeographicCRS base = geographic(); object = new DefaultGeocentricCRS(properties(base, geocentric), base.getDatum(), cs); cachedGeocentric = object; } @@ -795,30 +802,31 @@ public enum CommonCRS { public GeocentricCRS spherical() { GeocentricCRS object = cachedSpherical; if (object == 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, + * and share that CS instance for all other constants. + */ + SphericalCS cs = null; + if (this != DEFAULT) { + cs = (SphericalCS) DEFAULT.spherical().getCoordinateSystem(); + } 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); + } + } + // Use same name and datum than the geographic CRS. + final GeographicCRS base = geographic(); synchronized (this) { object = cachedSpherical; if (object == 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, - * and share that CS instance for all other constants. - */ - SphericalCS cs = null; - if (this == DEFAULT) { - final GeodeticAuthorityFactory factory = factory(); - if (factory != null) try { - 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); - } - } else { - cs = (SphericalCS) DEFAULT.spherical().getCoordinateSystem(); + if (cs == null) { + cs = (SphericalCS) StandardDefinitions.createCoordinateSystem(StandardDefinitions.SPHERICAL, true); } - // Use same name and datum than the geographic CRS. - final GeographicCRS base = geographic(); object = new DefaultGeocentricCRS(IdentifiedObjects.getProperties(base, exclude()), base.getDatum(), cs); cachedSpherical = object; } @@ -853,17 +861,20 @@ public enum CommonCRS { public 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) { + failure(this, "datum", e, datum); + } + final var ei = ellipsoid(); + final var pm = primeMeridian(); synchronized (this) { object = datum(cached); if (object == null) { - final GeodeticAuthorityFactory factory = factory(); - if (factory != null) try { - cached = object = factory.createGeodeticDatum(String.valueOf(datum)); - return object; - } catch (FactoryException e) { - failure(this, "datum", e, datum); - } - object = StandardDefinitions.createGeodeticDatum(datum, ellipsoid(), primeMeridian()); + object = StandardDefinitions.createGeodeticDatum(datum, ei, pm); cached = object; } } @@ -894,21 +905,22 @@ public enum CommonCRS { public 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) { - if (this == NAD83) { - 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); - } + object = StandardDefinitions.createEllipsoid(ellipsoid); cached = object; } } @@ -934,21 +946,22 @@ public enum CommonCRS { public 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) { - if (this != DEFAULT) { - 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(); - } + object = StandardDefinitions.primeMeridian(); cached = object; } } @@ -1375,17 +1388,20 @@ public enum CommonCRS { public 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) { - final GeodeticAuthorityFactory factory = factory(); - if (factory != null) try { - cached = object = factory.createVerticalCRS(String.valueOf(crs)); - return object; - } catch (FactoryException e) { - failure(this, "crs", e, crs); - } object = StandardDefinitions.createVerticalCRS(crs, datum()); } else { final VerticalCS cs = cs(); @@ -1441,17 +1457,20 @@ public enum CommonCRS { public 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) { - final GeodeticAuthorityFactory factory = factory(); - if (factory != null) try { - cached = object = factory.createVerticalDatum(String.valueOf(datum)); - return object; - } catch (FactoryException e) { - failure(this, "datum", e, datum); - } object = StandardDefinitions.createVerticalDatum(datum); } else { object = new DefaultVerticalDatum(properties(datum), VerticalDatumType.valueOf(name())); @@ -1809,20 +1828,20 @@ public enum CommonCRS { public 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) { - if (this == UNIX) { - object = JAVA.datum(); // Share the same instance for UNIX and JAVA. + final Map<String,?> properties; + if (key == Vocabulary.Keys.Time_1) { + properties = properties(Vocabulary.formatInternational(key, "Unix/POSIX")); } else { - 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, new Date(epoch)); + properties = properties(key); } + object = new DefaultTemporalDatum(properties, new Date(epoch)); cached = object; } }