github-actions[bot] commented on code in PR #65644:
URL: https://github.com/apache/doris/pull/65644#discussion_r3600047872


##########
fe/fe-core/src/main/java/org/apache/doris/fs/FileSystemPluginManager.java:
##########
@@ -80,9 +84,18 @@ public class FileSystemPluginManager {
     public void loadBuiltins() {
         ServiceLoader.load(FileSystemProvider.class)
                 .forEach(p -> {
-                    providers.add(p);
-                    
DatasourcePrintableMap.registerSensitiveKeys(p.sensitivePropertyKeys());
-                    LOG.info("Registered built-in filesystem provider: {}", 
p.name());
+                    try {
+                        // Snapshot self-reported metadata before publishing 
the provider
+                        // so one throwing implementation is rejected cleanly 
instead of
+                        // aborting startup or being active without an 
inventory row.
+                        
PluginRegistry.getInstance().registerBuiltin(PLUGIN_FAMILY, p);

Review Comment:
   [P2] Keep registry publication after sensitive-key discovery. 
sensitivePropertyKeys() is overridable provider code and can throw; because 
this row is inserted first, the catch below skips the provider but cannot 
remove the record, so information_schema.plugins permanently advertises a 
BUILTIN provider that the runtime manager rejected. Snapshot the sensitive keys 
before mutating either store (and honor one registration decision atomically). 
The external loop needs the same failure ordering/cleanup: it currently adds 
the provider before this callback and before the registry row.



##########
fe/fe-extension-loader/src/main/java/org/apache/doris/extension/loader/DirectoryPluginRuntimeManager.java:
##########
@@ -265,22 +288,90 @@ private PluginHandle<F> loadFromPluginDir(Path pluginDir, 
ClassLoader parent, Cl
                     "Failed to get plugin name from discovered factory in " + 
normalizedDir,
                     e);
         }
-        if (pluginName == null || pluginName.trim().isEmpty()) {
+        String nameValidationError = PluginNames.validate(pluginName);
+        if (nameValidationError != null) {
             closeClassLoader(classLoader);
             throw new PluginLoadException(
                     normalizedDir,
                     LoadFailure.STAGE_INSTANTIATE,
-                    "Plugin name is empty for directory: " + normalizedDir,
+                    "Invalid plugin name for directory " + normalizedDir + ": 
" + nameValidationError,
                     null);
         }
 
+        String description;
+        try {
+            description = factory.description();
+        } catch (RuntimeException e) {
+            closeClassLoader(classLoader);
+            throw new PluginLoadException(
+                    normalizedDir,
+                    LoadFailure.STAGE_INSTANTIATE,
+                    "Failed to get plugin description from discovered factory 
in " + normalizedDir,
+                    e);
+        }
+
+        String implementationVersion = 
readImplementationVersion(factory.getClass(), allJars);
+
         return new PluginHandle<>(
                 pluginName.trim(),
                 normalizedDir,
                 allJars,
                 classLoader,
                 factory,
-                Instant.now());
+                Instant.now(),
+                description,
+                implementationVersion);
+    }
+
+    /**
+     * Reads Implementation-Version from the MANIFEST of the jar that defined 
the
+     * factory class: the class's code source when available (covers layouts 
where
+     * the service descriptor sits in a root jar but the implementation lives 
in
+     * lib/), otherwise the first candidate jar containing the class entry.
+     * Version is display-only metadata: failures degrade to null instead of
+     * failing the load.
+     */
+    private String readImplementationVersion(Class<?> factoryClass, List<Path> 
candidateJars) {
+        Path definingJar = jarOf(factoryClass);
+        if (definingJar != null) {
+            try (JarFile jarFile = new JarFile(definingJar.toFile())) {
+                return manifestImplementationVersion(jarFile);
+            } catch (IOException ignored) {
+                // Fall through to scanning the candidate jars.
+            }
+        }
+        String classEntry = factoryClass.getName().replace('.', '/') + 
".class";
+        for (Path jar : candidateJars) {
+            try (JarFile jarFile = new JarFile(jar.toFile())) {
+                if (jarFile.getEntry(classEntry) == null) {
+                    continue;
+                }
+                return manifestImplementationVersion(jarFile);
+            } catch (IOException ignored) {
+                // Display-only metadata; fall through to the next candidate 
jar.
+            }
+        }
+        return null;
+    }
+
+    private static String manifestImplementationVersion(JarFile jarFile) 
throws IOException {
+        Manifest manifest = jarFile.getManifest();
+        return manifest == null ? null

Review Comment:
   [P2] Honor package-specific Implementation-Version attributes. Java 
manifests allow package versioning in a named section such as Name: 
com/acme/plugin/, and that value overrides the main section for classes in that 
package. This helper reads only main attributes, so a factory with a valid 
package-section version is reported with the wrong main value or NULL. Read the 
factory package section first with main attributes as fallback, and cover that 
manifest layout.



##########
fe/fe-extension-spi/src/main/java/org/apache/doris/extension/spi/PluginFactory.java:
##########
@@ -31,6 +31,17 @@ public interface PluginFactory {
      */
     String name();
 
+    /**
+     * Returns a one-line human-readable description of the plugin.
+     *
+     * <p>Snapshotted once at load time by the loader; never invoked at query 
time.</p>
+     *
+     * @return plugin description, empty by default
+     */
+    default String description() {

Review Comment:
   [P1] Preserve compatibility for existing factory jars. A factory compiled 
against the old SPI can legally inherit description() from an unrelated 
interface; adding this default creates two maximally-specific implementations 
and can make the new call throw IncompatibleClassChangeError. The loader 
catches only RuntimeException, so this LinkageError escapes per-plugin 
isolation without closing the classloader and can abort the family load or FE 
startup. Put optional metadata on a new subinterface with an empty fallback for 
old factories, and add an old-SPI binary compatibility fixture.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to