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 149bb5fa11031d98eeff42834f0cd9e4e8e2ec79
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Nov 29 12:48:09 2023 +0100

    Show the module path in the configuration, in addition to the class path.
    Since SIS 1.4, the class path is often empty.
---
 .../org/apache/sis/storage/gpx/StoreProvider.java  |   2 +-
 .../main/org/apache/sis/setup/About.java           | 118 +++++++++------------
 .../org/apache/sis/util/resources/Vocabulary.java  |  10 +-
 .../sis/util/resources/Vocabulary.properties       |   2 +-
 .../sis/util/resources/Vocabulary_fr.properties    |   2 +-
 5 files changed, 60 insertions(+), 74 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/gpx/StoreProvider.java
 
b/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/gpx/StoreProvider.java
index 48e63bbf5b..91f01b1d00 100644
--- 
a/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/gpx/StoreProvider.java
+++ 
b/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/gpx/StoreProvider.java
@@ -40,7 +40,7 @@ import org.apache.sis.util.Version;
  */
 @StoreMetadata(formatName    = StoreProvider.NAME,
                fileSuffixes  = "xml",
-               capabilities  = {Capability.READ, Capability.WRITE},
+               capabilities  = {Capability.READ, Capability.WRITE, 
Capability.CREATE},
                resourceTypes = {FeatureSet.class})
 public final class StoreProvider extends StaxDataStoreProvider {
     /**
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/About.java 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/About.java
index 3514eaca85..f492bbc746 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/About.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/About.java
@@ -33,7 +33,6 @@ import java.util.jar.Manifest;
 import java.util.logging.Level;
 import java.util.logging.Handler;
 import java.io.File;
-import java.io.FileFilter;
 import java.io.IOException;
 import java.text.Format;
 import java.text.DateFormat;
@@ -75,11 +74,11 @@ import static 
org.apache.sis.util.internal.StandardDateFormat.UTC;
  *   <li>Version numbers (SIS, Java, Operation system).</li>
  *   <li>Default locale, timezone and character encoding.</li>
  *   <li>Current directory, user home and Java home.</li>
- *   <li>Libraries on the classpath and extension directories.</li>
+ *   <li>Libraries on the module path.</li>
  * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.4
+ * @version 1.5
  * @since   0.3
  */
 public enum About {
@@ -146,7 +145,7 @@ public enum About {
      *
      * <ul>
      *   <li>JAR files in the extension directories</li>
-     *   <li>JAR files and directories in the application classpath</li>
+     *   <li>JAR files and directories in the application module path</li>
      * </ul>
      */
     LIBRARIES(Vocabulary.Keys.Libraries);
@@ -334,7 +333,7 @@ fill:   for (int i=0; ; i++) {
                                 .getMethod("providers", Locale.class, 
Vocabulary.class).invoke(null, locale, resources);
                         value = 
resources.getString(Vocabulary.Keys.EntryCount_1, children.length / 2);
                     } catch (ClassNotFoundException e) {
-                        // org.apache.sis.storage module not in the classpath.
+                        // org.apache.sis.storage module not on the module 
path.
                         
Logging.recoverableException(getLogger(Modules.STORAGE), About.class, 
"configuration", e);
                     } catch (ReflectiveOperationException e) {
                         value = Exceptions.unwrap(e).toString();
@@ -424,30 +423,30 @@ fill:   for (int i=0; ; i++) {
                 }
                 case 17: {
                     if (sections.contains(PATHS)) {
-                        nameKey = Vocabulary.Keys.TemporaryFiles;
-                        value = getProperty("java.io.tmpdir");
+                        nameKey = Vocabulary.Keys.JavaHome;
+                        value = javaHome = getProperty("java.home");
                     }
                     break;
                 }
                 case 18: {
                     if (sections.contains(PATHS)) {
-                        nameKey = Vocabulary.Keys.JavaHome;
-                        value = javaHome = getProperty("java.home");
+                        nameKey = Vocabulary.Keys.TemporaryFiles;
+                        value = getProperty("java.io.tmpdir");
                     }
                     break;
                 }
                 case 19: {
                     newSection = LIBRARIES;
                     if (sections.contains(LIBRARIES)) {
-                        nameKey = Vocabulary.Keys.JavaExtensions;
-                        value = classpath(getProperty("java.ext.dirs"), true);
+                        nameKey = Vocabulary.Keys.ModulePath;
+                        value = modulePath(getProperty("jdk.module.path"), 
false);
                     }
                     break;
                 }
                 case 20: {
                     if (sections.contains(LIBRARIES)) {
                         nameKey = Vocabulary.Keys.Classpath;
-                        value = classpath(getProperty("java.class.path"), 
false);
+                        value = modulePath(getProperty("java.class.path"), 
true);
                     }
                     break;
                 }
@@ -540,60 +539,50 @@ pathTree:   for (int j=0; ; j++) {
      * Returns a map of all JAR files or class directories found in the given 
paths,
      * associated to a description obtained from their {@code 
META-INF/MANIFEST.MF}.
      *
-     * @param  paths          the paths using the {@link 
File#pathSeparatorChar} separator.
-     * @param  asDirectories  {@code true} if the paths are directories, or 
{@code false} for JAR files.
+     * @param  paths      the paths using the {@link File#pathSeparatorChar} 
separator.
+     * @param  classpath  whether to scan the class-path manifest attribute.
      * @return the paths, or {@code null} if none.
      */
-    private static Map<File,CharSequence> classpath(final String paths, final 
boolean asDirectories) {
+    private static Map<File,CharSequence> modulePath(final String paths, final 
boolean classpath) {
         final Map<File,CharSequence> files = new LinkedHashMap<>();
-        return classpath(paths, null, asDirectories, files) ? files : null;
+        return modulePath(paths, File.pathSeparatorChar, classpath, null, 
files) ? files : null;
     }
 
     /**
-     * Implementation of {@link #classpath(String, boolean)} to be invoked 
recursively.
-     * The {@code paths} argument may contains many path separated by one of 
the
-     * following separators:
-     *
-     * <ul>
-     *   <li>If {@code directory} is null, then {@code paths} is assumed to be 
a
-     *       system property value using the {@link 
File#pathSeparatorChar}.</li>
-     *   <li>If {@code directory} is non-null, then {@code paths} is assumed 
to be
-     *       a {@code MANIFEST.MF} attribute using space as the path 
separator.</li>
-     * </ul>
+     * Implementation of {@link #modulePath(String, boolean)} to be invoked 
recursively.
+     * The {@code paths} argument may contain many paths separated by the 
given separator.
+     * That separator is usually {@link File#pathSeparatorChar}, except for 
the value of
+     * the {@code MANIFEST.MF} attribute in which case the separator is a 
space.
      *
-     * @param  paths          the paths using the separator described above.
-     * @param  directory      the directory of {@code MANIFEST.MF} classpath, 
or {@code null}.
-     * @param  asDirectories  {@code true} if the paths are directories, or 
{@code false} for JAR files.
-     * @param  files          where to add the paths.
+     * @param  paths      the paths using the specified path separator.
+     * @param  separator  the path separator: {@link File#pathSeparatorChar} 
or space.
+     * @param  classpath  whether to scan the class-path manifest attribute.
+     * @param  directory  the directory of {@code MANIFEST.MF} classpath, or 
{@code null}.
+     * @param  files      where to add the paths.
      * @return {@code true} if the given map has been changed as a result of 
this method call.
      */
-    private static boolean classpath(final String paths, final File directory,
-            final boolean asDirectories, final Map<File,CharSequence> files)
+    private static boolean modulePath(final String paths, final char 
separator, final boolean classpath,
+            final File directory, final Map<File,CharSequence> files)
     {
         if (paths == null) {
             return false;
         }
         boolean changed = false;
-        for (final CharSequence path : CharSequences.split(paths, (directory 
== null) ? File.pathSeparatorChar : ' ')) {
+        for (final CharSequence path : CharSequences.split(paths, separator)) {
             final File file = new File(directory, path.toString());
-            if (file.exists()) {
-                if (!asDirectories) {
-                    if (!files.containsKey(file)) {
-                        files.put(file, null);
-                        changed = true;
-                    }
-                } else {
-                    // If we are scanning extensions, then the path are 
directories
-                    // rather than files. So we need to scan the directory 
content.
-                    final JARFilter filter = new JARFilter();
-                    final File[] list = file.listFiles(filter);
-                    if (list != null) {
-                        Arrays.sort(list);
-                        for (final File ext : list) {
-                            if (!files.containsKey(ext)) {
-                                files.put(ext, null);
-                                changed = true;
-                            }
+            if (file.isFile()) {
+                if (!files.containsKey(file)) {
+                    files.put(file, null);
+                    changed = true;
+                }
+            } else if (file.isDirectory()) {
+                final File[] list = file.listFiles((pathname) -> 
pathname.getName().endsWith(".jar"));
+                if (list != null) {
+                    Arrays.sort(list);
+                    for (final File ext : list) {
+                        if (!files.containsKey(ext)) {
+                            files.put(ext, null);
+                            changed = true;
                         }
                     }
                 }
@@ -608,8 +597,7 @@ pathTree:   for (int j=0; ; j++) {
          */
         IOException error = null;
         for (final Map.Entry<File,CharSequence> entry : files.entrySet()) {
-            CharSequence title = entry.getValue();
-            if (title != null) {
+            if (entry.getValue() != null) {
                 continue;               // This file has already been 
processed by a recursive method invocation.
             }
             final File file = entry.getKey();
@@ -619,6 +607,7 @@ pathTree:   for (int j=0; ; j++) {
                     if (manifest != null) {
                         final Attributes attributes = 
manifest.getMainAttributes();
                         if (attributes != null) {
+                            CharSequence title;
                             title = 
concatenate(attributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE),
                                     
attributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION), false);
                             if (title == null) {
@@ -631,10 +620,16 @@ pathTree:   for (int j=0; ; j++) {
                                 }
                             }
                             entry.setValue(title);
-                            if 
(classpath(attributes.getValue(Attributes.Name.CLASS_PATH),
-                                    file.getParentFile(), false, files))
-                            {
-                                break;          // Necessary for avoiding 
ConcurrentModificationException.
+                            /*
+                             * If scanning a class path, this JAR file 
implicitly adds the content of the
+                             * CLASS-PATH attribute as transitive 
dependencies. If scanning a module path,
+                             * this is ignored.
+                             */
+                            if (classpath) {
+                                String cp = 
attributes.getValue(Attributes.Name.CLASS_PATH);
+                                if (modulePath(cp, ' ', true, 
file.getParentFile(), files)) {
+                                    break;          // Necessary for avoiding 
ConcurrentModificationException.
+                                }
                             }
                         }
                     }
@@ -775,15 +770,6 @@ pathTree:   for (int j=0; ; j++) {
         return df.format(Math.abs(offset), buffer.append(offset < 0 ? '-' : 
'+').append(' '), new FieldPosition(0));
     }
 
-    /**
-     * Filters the JAR files in an extension directory.
-     */
-    private static final class JARFilter implements FileFilter {
-        @Override public boolean accept(final File pathname) {
-            return pathname.getName().endsWith(".jar");
-        }
-    }
-
     /**
      * Returns the given file relative to the given root, or {@code null} if 
the root is not
      * a parent of that file.
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 7b67be2cf2..fc24f83221 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
@@ -684,11 +684,6 @@ public class Vocabulary extends IndexedResourceBundle {
          */
         public static final short Isolines = 252;
 
-        /**
-         * Java extensions
-         */
-        public static final short JavaExtensions = 109;
-
         /**
          * Java home directory
          */
@@ -849,6 +844,11 @@ public class Vocabulary extends IndexedResourceBundle {
          */
         public static final short ModifiedJulian = 136;
 
+        /**
+         * Module path
+         */
+        public static final short ModulePath = 109;
+
         /**
          * … {0} more…
          */
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
index e9abdbb809..4bfda2c7a8 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
@@ -141,7 +141,6 @@ Invalid                 = Invalid
 InverseOperation        = Inverse operation
 Interval                = Interval
 Isolines                = Isolines
-JavaExtensions          = Java extensions
 JavaHome                = Java home directory
 Julian                  = Julian
 Latitude                = Latitude
@@ -174,6 +173,7 @@ Minimum                 = Minimum
 MinimumValue            = Minimum value
 MissingValue            = Missing value
 ModifiedJulian          = Modified Julian
+ModulePath              = Module path
 More_1                  = \u2026 {0} more\u2026
 Multiplicity            = Multiplicity
 Name                    = Name
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
index 67bebdcb73..18ca8ac441 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
@@ -148,7 +148,6 @@ Invalid                 = Invalide
 InverseOperation        = Op\u00e9ration inverse
 Interval                = Intervalle
 Isolines                = Isolignes
-JavaExtensions          = Extensions du Java
 JavaHome                = R\u00e9pertoire du Java
 Julian                  = Julien
 Latitude                = Latitude
@@ -181,6 +180,7 @@ Minimum                 = Minimum
 MinimumValue            = Valeur minimale
 MissingValue            = Valeur manquante
 ModifiedJulian          = Julien modifi\u00e9
+ModulePath              = Chemin des modules
 More_1                  = \u2026 {0} de plus\u2026
 Multiplicity            = Multiplicit\u00e9
 Name                    = Nom

Reply via email to