This is an automated email from the ASF dual-hosted git repository.

vladimirsitnikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git

commit b15439e340b6c566fddc41874257d7a200455496
Author: Vladimir Sitnikov <[email protected]>
AuthorDate: Thu May 25 11:13:44 2023 +0300

    feat: use ServiceLoader for loading jmeter.gui.action.Command
---
 .../org/apache/jmeter/gui/action/ActionRouter.java | 72 +++++-----------------
 .../java/org/apache/jmeter/gui/action/Command.java |  2 +
 2 files changed, 17 insertions(+), 57 deletions(-)

diff --git 
a/src/core/src/main/java/org/apache/jmeter/gui/action/ActionRouter.java 
b/src/core/src/main/java/org/apache/jmeter/gui/action/ActionRouter.java
index 24536f7ec7..af91e3b52a 100644
--- a/src/core/src/main/java/org/apache/jmeter/gui/action/ActionRouter.java
+++ b/src/core/src/main/java/org/apache/jmeter/gui/action/ActionRouter.java
@@ -20,17 +20,13 @@ package org.apache.jmeter.gui.action;
 import java.awt.HeadlessException;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.io.File;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.CodeSource;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Optional;
+import java.util.ServiceLoader;
 import java.util.Set;
 
 import javax.swing.SwingUtilities;
@@ -38,7 +34,7 @@ import javax.swing.SwingUtilities;
 import org.apache.jmeter.exceptions.IllegalUserActionException;
 import org.apache.jmeter.gui.GuiPackage;
 import org.apache.jmeter.util.JMeterUtils;
-import org.apache.jorphan.reflect.ClassFinder;
+import org.apache.jorphan.reflect.LogAndIgnoreServiceLoadExceptionHandler;
 import org.apache.jorphan.util.JMeterError;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -309,35 +305,6 @@ public final class ActionRouter implements ActionListener {
         }
     }
 
-    @SuppressWarnings("deprecation")
-    private static List<String> findClassesThatExtend(String className, String 
excluding, String[] searchPath) throws IOException, ClassNotFoundException {
-
-        return ClassFinder.findClassesThatExtend(
-                searchPath, // strPathsOrJars - pathNames or jar files to 
search for classes
-                new Class[] { Class.forName(className) },
-                false, // innerClasses - should we include inner classes?
-                null, // contains - className should contain this string
-                // Ignore the classes which are specific to the reporting tool
-                excluding, // notContains - className should not contain this 
string
-                false); // annotations - true if classNames are annotations
-    }
-
-    private static Optional<String[]> getCodeSourceSearchPath() {
-        CodeSource codeSource = 
ActionRouter.class.getProtectionDomain().getCodeSource();
-        if (codeSource != null) {
-            try {
-                URL ownLocation = codeSource.getLocation();
-                File ownPath = new File(ownLocation.toURI());
-                if (ownPath.exists()) {
-                    return Optional.of(new String[] { 
ownPath.getAbsolutePath() });
-                }
-            } catch (URISyntaxException ex) {
-                log.debug("Can't get location for class sources", ex);
-            }
-        }
-        return Optional.empty();
-    }
-
     /**
      * Only for use by the JMeter.startGui.
      * This method must not be called by getInstance() as was done previously.
@@ -348,28 +315,19 @@ public final class ActionRouter implements ActionListener 
{
             return; // already done
         }
         try {
-            List<String> listClasses = 
findClassesThatExtend("org.apache.jmeter.gui.action.Command", // $NON-NLS-1$
-                    "org.apache.jmeter.report.gui", // $NON-NLS-1$
-                    JMeterUtils.getSearchPaths());
-
-            if (listClasses.isEmpty()) {
-                //fallback
-                Optional<String[]> codeSourceSearchPath = 
getCodeSourceSearchPath();
-                if (codeSourceSearchPath.isPresent()) {
-                    log.info("Using fallback search path");
-                    listClasses = 
findClassesThatExtend("org.apache.jmeter.gui.action.Command", // $NON-NLS-1$
-                            "org.apache.jmeter.report.gui", // $NON-NLS-1$
-                            codeSourceSearchPath.get());
-                }
-            }
-
-            if (listClasses.isEmpty()) {
-                log.error("!!!!!Uh-oh, didn't find any action handlers!!!!!");
-                throw new JMeterError("No action handlers found - check 
JMeterHome and libraries");
+            Collection<Command> commandServices = 
JMeterUtils.loadServicesAndScanJars(
+                    Command.class,
+                    ServiceLoader.load(Command.class),
+                    Thread.currentThread().getContextClassLoader(),
+                    new LogAndIgnoreServiceLoadExceptionHandler(log)
+            );
+
+            if (commandServices.isEmpty()) {
+                String message = "No implementations of " + Command.class + " 
found. Please ensure the classpath contains JMeter commands";
+                log.error(message);
+                throw new JMeterError(message);
             }
-            for (String strClassName : listClasses) {
-                Class<?> commandClass = Class.forName(strClassName);
-                Command command = (Command) 
commandClass.getDeclaredConstructor().newInstance();
+            for (Command command : commandServices) {
                 for (String commandName : command.getActionNames()) {
                     Set<Command> commandObjects = 
commands.computeIfAbsent(commandName, k -> new HashSet<>());
                     commandObjects.add(command);
diff --git a/src/core/src/main/java/org/apache/jmeter/gui/action/Command.java 
b/src/core/src/main/java/org/apache/jmeter/gui/action/Command.java
index 97dcd1e70b..e7284f8fec 100644
--- a/src/core/src/main/java/org/apache/jmeter/gui/action/Command.java
+++ b/src/core/src/main/java/org/apache/jmeter/gui/action/Command.java
@@ -21,7 +21,9 @@ import java.awt.event.ActionEvent;
 import java.util.Set;
 
 import org.apache.jmeter.exceptions.IllegalUserActionException;
+import org.apache.jorphan.reflect.JMeterService;
 
+@JMeterService
 public interface Command {
     void doAction(ActionEvent e) throws IllegalUserActionException;
 

Reply via email to