You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2026/05/05 13:45:40 UTC
(sis) 02/03: Workaround an `IllegalAccessException` caused by module boundaries. https://issues.apache.org/jira/browse/SIS-632
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
commit 49a5bd39ee0c372b563e8686984cc889720272a9
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Tue May 5 14:47:27 2026 +0200
Workaround an `IllegalAccessException` caused by module boundaries.
https://issues.apache.org/jira/browse/SIS-632
---
.../resources/IndexedResourceCompiler.java | 44 ++++++++++++++--------
.../org/apache/sis/cloud/aws/s3/Resources.java | 14 +++++++
.../org/apache/sis/feature/internal/Resources.java | 14 +++++++
.../apache/sis/metadata/internal/Resources.java | 14 +++++++
.../org/apache/sis/map/internal/Resources.java | 14 +++++++
.../referencing/gazetteer/internal/Resources.java | 14 +++++++
.../apache/sis/referencing/internal/Resources.java | 14 +++++++
.../apache/sis/storage/geotiff/base/Resources.java | 14 +++++++
.../sis/storage/netcdf/internal/Resources.java | 14 +++++++
.../apache/sis/storage/sql/feature/Resources.java | 14 +++++++
.../org/apache/sis/storage/internal/Resources.java | 14 +++++++
.../main/org/apache/sis/util/resources/Errors.java | 14 +++++++
.../apache/sis/util/resources/KeyConstants.java | 37 ++++++++++--------
.../org/apache/sis/util/resources/Messages.java | 14 +++++++
.../org/apache/sis/util/resources/Vocabulary.java | 14 +++++++
.../org/apache/sis/gui/internal/Resources.java | 14 +++++++
.../org/apache/sis/storage/panama/Resources.java | 14 +++++++
17 files changed, 259 insertions(+), 32 deletions(-)
diff --git a/buildSrc/src/main/java/org/apache/sis/buildtools/resources/IndexedResourceCompiler.java b/buildSrc/src/main/java/org/apache/sis/buildtools/resources/IndexedResourceCompiler.java
index ac991b2504..ebd9b436f0 100644
--- a/buildSrc/src/main/java/org/apache/sis/buildtools/resources/IndexedResourceCompiler.java
+++ b/buildSrc/src/main/java/org/apache/sis/buildtools/resources/IndexedResourceCompiler.java
@@ -30,7 +30,6 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
-import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
@@ -122,13 +121,13 @@ public class IndexedResourceCompiler {
* Integer IDs allocated to resource keys.
* This map will be shared for all languages of a given resource bundle.
*/
- private final Map<Integer,String> allocatedIDs = new HashMap<>();
+ private final Map<Integer, String> allocatedIDs = new HashMap<>();
/**
* Resource keys and their localized values.
* This map will be cleared for each language in a resource bundle.
*/
- private final Map<Object,Object> resources = new HashMap<>();
+ private final Map<Object, Object> resources = new HashMap<>();
/**
* Buffer to use for writing UTF data in an array of bytes.
@@ -191,12 +190,12 @@ public class IndexedResourceCompiler {
* @param resourcesToProcess the files to filter. This map will be modified in-place.
* @param checkSourceExists whether to check that the Java source file exists.
*/
- static void filterLanguages(final SortedMap<File,Boolean> resourcesToProcess, final boolean checkSourceExists) {
- final Iterator<Map.Entry<File,Boolean>> it = resourcesToProcess.entrySet().iterator();
- Map.Entry<File,Boolean> baseEntry = null;
+ static void filterLanguages(final SortedMap<File, Boolean> resourcesToProcess, final boolean checkSourceExists) {
+ final Iterator<Map.Entry<File, Boolean>> it = resourcesToProcess.entrySet().iterator();
+ Map.Entry<File, Boolean> baseEntry = null;
String baseName = null;
while (it.hasNext()) {
- final Map.Entry<File,Boolean> entry = it.next();
+ final Map.Entry<File, Boolean> entry = it.next();
final File file = entry.getKey();
if (baseName != null && file.getName().startsWith(baseName)) {
if (baseEntry != null) {
@@ -248,7 +247,7 @@ public class IndexedResourceCompiler {
if (files == null) {
throw new FileNotFoundException(directory + " not found or is not a directory.");
}
- final var resourcesToProcess = new TreeMap<File,Boolean>();
+ final var resourcesToProcess = new TreeMap<File, Boolean>();
for (final File file : files) {
final String name = file.getName();
if (!name.isEmpty() && name.charAt(0) != '.') {
@@ -264,7 +263,7 @@ public class IndexedResourceCompiler {
}
}
filterLanguages(resourcesToProcess, true);
- for (final Map.Entry<File,Boolean> entry : resourcesToProcess.entrySet()) {
+ for (final Map.Entry<File, Boolean> entry : resourcesToProcess.entrySet()) {
final File source = entry.getKey();
if (entry.getValue()) {
onJavaSource(new File(source.getParentFile(), getBaseName(source) + JAVA_EXT));
@@ -299,7 +298,7 @@ public class IndexedResourceCompiler {
* @throws IOException if an error occurred while reading the source file.
*/
private void loadKeyValues() throws IOException {
- try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(bundleClass), JAVA_ENCODING))) {
+ try (var in = new BufferedReader(new InputStreamReader(new FileInputStream(bundleClass), JAVA_ENCODING))) {
String line;
while ((line = in.readLine()) != null) {
if ((line = line.trim()).startsWith(KEY_MODIFIERS)) {
@@ -399,7 +398,7 @@ public class IndexedResourceCompiler {
*/
private static Properties loadRawProperties(final File file) throws IOException {
final Properties properties;
- try (InputStream input = new FileInputStream(file)) {
+ try (var input = new FileInputStream(file)) {
properties = new Properties();
properties.load(input);
}
@@ -424,7 +423,7 @@ public class IndexedResourceCompiler {
private void loadProperties(final File file) throws IOException {
resources.clear();
final Properties properties = loadRawProperties(file);
- for (final Map.Entry<Object,Object> entry : properties.entrySet()) {
+ for (final Map.Entry<Object, Object> entry : properties.entrySet()) {
final String key = (String) entry.getKey();
final String value = (String) entry.getValue();
/*
@@ -496,7 +495,7 @@ public class IndexedResourceCompiler {
private static String toMessageFormatString(final String text) {
int level = 0;
int last = -1;
- final StringBuilder buffer = new StringBuilder(text);
+ final var buffer = new StringBuilder(text);
search: for (int i=0; i<buffer.length(); i++) { // Length of `buffer` will vary.
switch (buffer.charAt(i)) {
/*
@@ -559,7 +558,7 @@ search: for (int i=0; i<buffer.length(); i++) { // Length of `bu
private byte[] writeUTF() throws IOException {
bufferUTF.reset();
final int count = allocatedIDs.isEmpty() ? 0 : Collections.max(allocatedIDs.keySet());
- try (DataOutputStream out = new DataOutputStream(bufferUTF)) {
+ try (var out = new DataOutputStream(bufferUTF)) {
out.writeInt(count);
for (int i=1; i<=count; i++) {
final String value = (String) resources.get(allocatedIDs.get(i));
@@ -616,6 +615,19 @@ search: for (int i=0; i<buffer.length(); i++) { // Length of `bu
buffer.append(line).append(lineSeparator);
} while (!pattern.matcher(line).matches());
}
+ buffer.append(lineSeparator)
+ .append(" /**").append(lineSeparator)
+ .append(" * Returns the value of a field declared in this {@code Keys} class.").append(lineSeparator)
+ .append(" * This method is needed for encapsulation reason, because classes in").append(lineSeparator)
+ .append(" * other modules cannot access this class even by reflection.").append(lineSeparator)
+ .append(" */").append(lineSeparator)
+ .append(" @Override").append(lineSeparator)
+ .append(" protected Object getStaticValue(final Field field) throws IllegalAccessException {").append(lineSeparator)
+ .append(" if (field.getDeclaringClass() == Keys.class) {").append(lineSeparator)
+ .append(" return field.get(null);").append(lineSeparator)
+ .append(" }").append(lineSeparator)
+ .append(" throw new IllegalAccessException();").append(lineSeparator)
+ .append(" }").append(lineSeparator);
/*
* Starting from this point, the content that we are going to write in the buffer
* may be different than the file content. Remember the buffer position in order
@@ -635,7 +647,7 @@ search: for (int i=0; i<buffer.length(); i++) { // Length of `bu
if (message != null) {
message = message.replace('\t', ' ');
buffer.append(KEY_MARGIN).append("/**").append(lineSeparator);
- while (((message=message.trim()).length()) != 0) {
+ while (((message = message.trim()).length()) != 0) {
buffer.append(KEY_MARGIN).append(" * ");
int stop = message.indexOf('\n');
if (stop < 0) {
@@ -754,7 +766,7 @@ search: for (int i=0; i<buffer.length(); i++) { // Length of `bu
private void warning(final File file, final String key,
final String message, final Exception exception)
{
- final StringBuilder buffer = new StringBuilder("ERROR ");
+ final var buffer = new StringBuilder("ERROR ");
if (file != null) {
String filename = file.getPath();
if (filename.endsWith(PROPERTIES_EXT)) {
diff --git a/endorsed/src/org.apache.sis.cloud.aws/main/org/apache/sis/cloud/aws/s3/Resources.java b/endorsed/src/org.apache.sis.cloud.aws/main/org/apache/sis/cloud/aws/s3/Resources.java
index d7afb279a9..cf5e2608c1 100644
--- a/endorsed/src/org.apache.sis.cloud.aws/main/org/apache/sis/cloud/aws/s3/Resources.java
+++ b/endorsed/src/org.apache.sis.cloud.aws/main/org/apache/sis/cloud/aws/s3/Resources.java
@@ -17,6 +17,7 @@
package org.apache.sis.cloud.aws.s3;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.MissingResourceException;
import org.apache.sis.util.resources.KeyConstants;
@@ -51,6 +52,19 @@ class Resources extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* Cannot change a relative path to an absolute path.
*/
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources.java
index 8f099fc9d1..ab67b06ea4 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources.java
@@ -17,6 +17,7 @@
package org.apache.sis.feature.internal;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Map;
import java.util.Locale;
import java.util.MissingResourceException;
@@ -54,6 +55,19 @@ public class Resources extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* Feature type ‘{0}’ is abstract.
*/
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources.java
index 34598f5563..d2322ec966 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources.java
@@ -17,6 +17,7 @@
package org.apache.sis.metadata.internal;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.MissingResourceException;
import org.opengis.util.InternationalString;
@@ -53,6 +54,19 @@ public class Resources extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* Connection to “{0}” database is already initialized.
*/
diff --git a/endorsed/src/org.apache.sis.portrayal/main/org/apache/sis/map/internal/Resources.java b/endorsed/src/org.apache.sis.portrayal/main/org/apache/sis/map/internal/Resources.java
index e80ebd1814..a667a65cfd 100644
--- a/endorsed/src/org.apache.sis.portrayal/main/org/apache/sis/map/internal/Resources.java
+++ b/endorsed/src/org.apache.sis.portrayal/main/org/apache/sis/map/internal/Resources.java
@@ -17,6 +17,7 @@
package org.apache.sis.map.internal;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.MissingResourceException;
import org.apache.sis.util.resources.KeyConstants;
@@ -49,6 +50,19 @@ public class Resources extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* The “{0}” resource specifies an invalid conversion from pixel coordinates to the “{1}”
* coordinate reference system.
diff --git a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/internal/Resources.java b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/internal/Resources.java
index e88d344cb3..d83e59997b 100644
--- a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/internal/Resources.java
+++ b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/internal/Resources.java
@@ -17,6 +17,7 @@
package org.apache.sis.referencing.gazetteer.internal;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
@@ -54,6 +55,19 @@ public class Resources extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* Location type parent already has a child named “{0}”.
*/
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources.java
index 641280441a..75a81983ce 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources.java
@@ -17,6 +17,7 @@
package org.apache.sis.referencing.internal;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
@@ -54,6 +55,19 @@ public class Resources extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* Accuracy declared in a geodetic dataset.
*/
diff --git a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/base/Resources.java b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/base/Resources.java
index e9bde86ae6..fdd6002468 100644
--- a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/base/Resources.java
+++ b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/base/Resources.java
@@ -17,6 +17,7 @@
package org.apache.sis.storage.geotiff.base;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.MissingResourceException;
import org.opengis.util.InternationalString;
@@ -53,6 +54,19 @@ public class Resources extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* Cannot compute the grid geometry of “{0}” GeoTIFF file.
*/
diff --git a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/internal/Resources.java b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/internal/Resources.java
index 5c37f894fb..26b5fa05ae 100644
--- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/internal/Resources.java
+++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/internal/Resources.java
@@ -17,6 +17,7 @@
package org.apache.sis.storage.netcdf.internal;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.MissingResourceException;
import org.opengis.util.InternationalString;
@@ -53,6 +54,19 @@ public class Resources extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* NetCDF file “{0}” provides an ambiguous axis direction for variable “{1}”. It could be
* {2} or {3}.
diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Resources.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Resources.java
index 1edcfa8eac..225bddc0ed 100644
--- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Resources.java
+++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Resources.java
@@ -17,6 +17,7 @@
package org.apache.sis.storage.sql.feature;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.MissingResourceException;
import org.opengis.util.InternationalString;
@@ -53,6 +54,19 @@ public class Resources extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* Assume database byte/tinyint unsigned, due to a lack of metadata.
*/
diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/internal/Resources.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/internal/Resources.java
index 4f451dffab..a3b4fc5f6b 100644
--- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/internal/Resources.java
+++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/internal/Resources.java
@@ -17,6 +17,7 @@
package org.apache.sis.storage.internal;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.MissingResourceException;
import org.opengis.util.InternationalString;
@@ -53,6 +54,19 @@ public class Resources extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* Name “{3}” is ambiguous because it can be understood as either “{1}” or “{2}” in the context
* of “{0}” data.
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors.java
index 860b837840..ae65d1bfd1 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors.java
@@ -17,6 +17,7 @@
package org.apache.sis.util.resources;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Map;
import java.util.Locale;
import java.util.MissingResourceException;
@@ -57,6 +58,19 @@ public class Errors extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* ‘{0}’ is already initialized.
*/
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/KeyConstants.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/KeyConstants.java
index 0c66565b3a..2be050872f 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/KeyConstants.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/KeyConstants.java
@@ -20,7 +20,6 @@ import java.util.Arrays;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import org.apache.sis.util.ArraysExt;
-import org.apache.sis.util.CharSequences;
/**
@@ -32,12 +31,7 @@ import org.apache.sis.util.CharSequences;
*
* @see IndexedResourceBundle#getKeyConstants()
*/
-public class KeyConstants {
- /**
- * The class that defines key constants.
- */
- private final Class<?> keysClass;
-
+public abstract class KeyConstants {
/**
* The key names in the exact same order as {@link IndexedResourceBundle#values}.
* This is usually not needed, but may be created from the {@code Keys} inner class in some occasions.
@@ -51,15 +45,26 @@ public class KeyConstants {
* For sub-classes constructors only.
*/
protected KeyConstants() {
- keysClass = getClass();
}
/**
- * Creates a new instance for key constants defined in an independent class.
+ * Returns the value of the given static field.
+ * Subclasses should implement this method as below:
+ *
+ * {@snippet lang="java" :
+ * return field.get(null);
+ * }
+ *
+ * This implementation must be provided by subclasses for Java security reason.
+ * This is because this {@code KeyConstants} class is not allowed to perform the
+ * above call if the module that provides the {@code KeyConstants} subclass does
+ * not export the package that contain the subclass.
+ *
+ * @param field the field for which to get the value.
+ * @return value of the given field.
+ * @throws IllegalAccessException if access to the field is denied.
*/
- KeyConstants(final Class<?> keysClass) {
- this.keysClass = keysClass;
- }
+ protected abstract Object getStaticValue(Field field) throws IllegalAccessException;
/**
* Returns the internal array of key names. <strong>Do not modify the returned array.</strong>
@@ -73,11 +78,11 @@ public class KeyConstants {
String[] names;
int length = 0;
try {
- final Field[] fields = keysClass.getFields();
+ final Field[] fields = getClass().getFields();
names = new String[fields.length];
for (final Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) && field.getType() == Short.TYPE) {
- final int index = Short.toUnsignedInt((Short) field.get(null)) - IndexedResourceBundle.FIRST;
+ final int index = Short.toUnsignedInt((Short) getStaticValue(field)) - IndexedResourceBundle.FIRST;
if (index >= length) {
length = index + 1;
if (length > names.length) {
@@ -89,7 +94,7 @@ public class KeyConstants {
}
}
} catch (IllegalAccessException e) {
- names = CharSequences.EMPTY_ARRAY;
+ throw new IllegalCallerException(e);
}
keys = ArraysExt.resize(names, length);
}
@@ -118,6 +123,6 @@ public class KeyConstants {
* Returns the numerical value for the key of the given name.
*/
final short getKeyValue(final String name) throws NoSuchFieldException, IllegalAccessException {
- return (Short) keysClass.getField(name).get(null);
+ return (Short) getStaticValue(getClass().getField(name));
}
}
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Messages.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Messages.java
index 2a661986a5..fec0b6a6d7 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Messages.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Messages.java
@@ -17,6 +17,7 @@
package org.apache.sis.util.resources;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.MissingResourceException;
import org.opengis.util.InternationalString;
@@ -48,6 +49,19 @@ public class Messages extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* {0} “{1}” is already registered. The second instance will be ignored.
*/
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
index 5400228dde..db82cf3935 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
@@ -17,6 +17,7 @@
package org.apache.sis.util.resources;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Map;
import java.util.Locale;
import java.util.MissingResourceException;
@@ -49,6 +50,19 @@ public class Vocabulary extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* Abstract
*/
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources.java
index c789f97385..49f9abb6d2 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources.java
@@ -17,6 +17,7 @@
package org.apache.sis.gui.internal;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.MissingResourceException;
import javafx.event.ActionEvent;
@@ -54,6 +55,19 @@ public class Resources extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* About…
*/
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 d4b4c8f13a..4c728ce99d 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
@@ -17,6 +17,7 @@
package org.apache.sis.storage.panama;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.MissingResourceException;
import org.opengis.util.InternationalString;
@@ -53,6 +54,19 @@ public class Resources extends IndexedResourceBundle {
private Keys() {
}
+ /**
+ * Returns the value of a field declared in this {@code Keys} class.
+ * This method is needed for encapsulation reason, because classes in
+ * other modules cannot access this class even by reflection.
+ */
+ @Override
+ protected Object getStaticValue(final Field field) throws IllegalAccessException {
+ if (field.getDeclaringClass() == Keys.class) {
+ return field.get(null);
+ }
+ throw new IllegalAccessException();
+ }
+
/**
* Allowed {0} drivers for opening the file.
*/