Repository: sermant-io/Sermant (java)

Issue:
Multiple dynamic mountings do not support different agent directories.
### What happened?

After the plug-in is mounted for the first time, run the uninstall-agent command to uninstall the plug-in. When the plug-in is mounted again, the agent directory of the plug-in cannot be modified and must be the same as the directory of the first time.

### How can we reproduce it (as minimally and precisely as possible)?

The plug-in is dynamically loaded for multiple times and uninstalled by running the unstall-agent command. The agent directory path of the plug-in is different each time.

### Anything else we need to know?

_No response_

### Sermant version

<details>
2.0.0
</details>


### OS version

<details>

```console
# On Linux:
$ cat /etc/os-release
# paste output here
$ uname -a
# paste output here

# On Windows:
C:\> wmic os get Caption, Version, BuildNumber, OSArchitecture
# paste output here
```
</details>


Pull request:
fix_2.1.x: support dynamic install agent multi-times with different agent directory
**What type of PR is this?**

Bug

**What this PR does / why we need it?**

Currently when users dynamic install agent at the second time, the directory of new agent can not be a custom path. So this PR aims to fix this issue

**Which issue(s) this PR fixes？**

Fixes #1687

**Does this PR introduce a user-facing change?**

No

<!-- Follow this checklist to help us incorporate your contribution quickly and easily: -->

## Checklist
- [x] Make sure there is a [GitHub_issue](https://github.com/sermant-io/Sermant/issues) related with this PR before you start working on it.
- [x] Make sure you have squashed your change to one single commit.
- [x] GitHub Actions works fine in this PR.


Patch:
diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/AgentCoreEntrance.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/AgentCoreEntrance.java
index c048519ff..e7d93de00 100644
--- a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/AgentCoreEntrance.java
+++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/AgentCoreEntrance.java
@@ -19,6 +19,7 @@ package io.sermant.core;
 import io.sermant.core.classloader.ClassLoaderManager;
 import io.sermant.core.common.AgentType;
 import io.sermant.core.common.BootArgsIndexer;
+import io.sermant.core.common.CommonConstant;
 import io.sermant.core.common.LoggerFactory;
 import io.sermant.core.config.ConfigManager;
 import io.sermant.core.event.EventManager;
@@ -35,6 +36,7 @@ import io.sermant.core.plugin.agent.adviser.AdviserScheduler;
 import io.sermant.core.plugin.agent.info.EnhancementManager;
 import io.sermant.core.plugin.agent.template.DefaultAdviser;
 import io.sermant.core.service.ServiceManager;
+import io.sermant.core.utils.FileUtils;
 import io.sermant.god.common.SermantManager;
 
 import java.lang.instrument.Instrumentation;
@@ -90,6 +92,8 @@ public class AgentCoreEntrance {
         LoggerFactory.initDefaultLogger(artifact);
         adviserCache = new DefaultAdviser();
 
+        FileUtils.setAgentPath((String) argsMap.get(CommonConstant.AGENT_PATH_KEY));
+
         // Initialize the classloader of framework
         ClassLoaderManager.init(argsMap);
 
diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/common/CommonConstant.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/common/CommonConstant.java
index e2aa2b06d..7533d49b2 100644
--- a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/common/CommonConstant.java
+++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/common/CommonConstant.java
@@ -127,6 +127,11 @@ public class CommonConstant {
      */
     public static final String ARTIFACT_NAME_KEY = "artifact";
 
+    /**
+     * The key of agent path
+     */
+    public static final String AGENT_PATH_KEY = "agentPath";
+
     private CommonConstant() {
     }
 }
diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/plugin/classloader/PluginClassLoader.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/plugin/classloader/PluginClassLoader.java
index 368ddcd19..6c74d00c7 100644
--- a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/plugin/classloader/PluginClassLoader.java
+++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/plugin/classloader/PluginClassLoader.java
@@ -20,10 +20,8 @@ import io.sermant.core.common.LoggerFactory;
 import io.sermant.core.config.ConfigManager;
 import io.sermant.core.plugin.agent.config.AgentConfig;
 
-import java.io.IOException;
 import java.net.URL;
 import java.net.URLClassLoader;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.logging.Level;
@@ -152,17 +150,6 @@ public class PluginClassLoader extends URLClassLoader {
         return clazz;
     }
 
-    @Override
-    public Enumeration<URL> getResources(String name) throws IOException {
-        // Due to class isolation, the service loader does not obtain the service provider from the parent
-        // classloader, but returns only the resources in current classloader
-        if (name.startsWith("META-INF/services/")) {
-            return findResources(name);
-        }
-
-        return super.getResources(name);
-    }
-
     /**
      * Load classes only through Sermant's own search path, not using localClassLoader, which would otherwise cause
      * stackoverflow
diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/utils/FileUtils.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/utils/FileUtils.java
index 9174a020a..c5f6ba8bf 100644
--- a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/utils/FileUtils.java
+++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/utils/FileUtils.java
@@ -52,8 +52,7 @@ public class FileUtils {
 
     private static final String[] INVALID_SYMBOL = {"../", "..\\"};
 
-    private static final String AGENT_PATH = new File(new File(FileUtils.class.getProtectionDomain().getCodeSource()
-            .getLocation().getPath()).getParent()).getParent();
+    private static String agentPath;
 
     /**
      * file name of unmatched class name
@@ -79,7 +78,7 @@ public class FileUtils {
      * @return path
      */
     public static String getAgentPath() {
-        return AGENT_PATH;
+        return agentPath;
     }
 
     /**
@@ -89,7 +88,7 @@ public class FileUtils {
      * @return fixed path
      */
     public static String validatePath(String path) {
-        if (!path.startsWith(AGENT_PATH)) {
+        if (!path.startsWith(agentPath)) {
             return "";
         }
 
@@ -288,7 +287,7 @@ public class FileUtils {
         AgentConfig config = ConfigManager.getConfig(AgentConfig.class);
         String preFilterPath = config.getPreFilterPath();
         if (StringUtils.isEmpty(preFilterPath)) {
-            preFilterPath = AGENT_PATH;
+            preFilterPath = agentPath;
         }
         String preFilterFile = config.getPreFilterFile();
         if (StringUtils.isEmpty(preFilterFile)) {
@@ -296,4 +295,8 @@ public class FileUtils {
         }
         return preFilterPath + File.separatorChar + preFilterFile;
     }
+
+    public static void setAgentPath(String path) {
+        agentPath = path;
+    }
 }


Test patch:
diff --git a/sermant-agentcore/sermant-agentcore-core/src/test/java/io/sermant/core/utils/FileUtilsTest.java b/sermant-agentcore/sermant-agentcore-core/src/test/java/io/sermant/core/utils/FileUtilsTest.java
index 66d3abea9..0654e7236 100644
--- a/sermant-agentcore/sermant-agentcore-core/src/test/java/io/sermant/core/utils/FileUtilsTest.java
+++ b/sermant-agentcore/sermant-agentcore-core/src/test/java/io/sermant/core/utils/FileUtilsTest.java
@@ -29,7 +29,7 @@ public class FileUtilsTest {
     @Test
     public void testPath() {
         String pathValid = FileUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath();
-        Assert.assertEquals(pathValid, FileUtils.validatePath(pathValid));
+        FileUtils.setAgentPath(pathValid);
         String pathInvalid = "/test/path";
         Assert.assertEquals("", FileUtils.validatePath(pathInvalid));
         String pathInvalidSymbolA = pathValid + "../" + "/test";
diff --git a/sermant-agentcore/sermant-agentcore-implement/src/test/java/io/sermant/implement/service/hotplugging/listener/HotPluggingListenerTest.java b/sermant-agentcore/sermant-agentcore-implement/src/test/java/io/sermant/implement/service/hotplugging/listener/HotPluggingListenerTest.java
index 8b4b81838..7705cc958 100644
--- a/sermant-agentcore/sermant-agentcore-implement/src/test/java/io/sermant/implement/service/hotplugging/listener/HotPluggingListenerTest.java
+++ b/sermant-agentcore/sermant-agentcore-implement/src/test/java/io/sermant/implement/service/hotplugging/listener/HotPluggingListenerTest.java
@@ -23,6 +23,7 @@ import io.sermant.core.operation.OperationManager;
 import io.sermant.core.operation.converter.api.YamlConverter;
 import io.sermant.core.service.dynamicconfig.common.DynamicConfigEvent;
 import io.sermant.core.service.dynamicconfig.common.DynamicConfigEventType;
+import io.sermant.core.utils.FileUtils;
 import io.sermant.core.utils.JarFileUtils;
 import io.sermant.core.utils.StringUtils;
 import io.sermant.implement.operation.converter.YamlConverterImpl;
@@ -84,6 +85,8 @@ public class HotPluggingListenerTest {
                 .thenReturn(YAML_CONVERTER);
         commandProcessorMockedStatic.verify(() -> CommandProcessor.process(any()), times(0));
         jarFileUtilsMockedStatic.when(() -> JarFileUtils.getManifestAttr(any(), anyString())).thenReturn("1.0.0");
+        String pathValid = FileUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath();
+        FileUtils.setAgentPath(pathValid);
         Map<String, Object> argsMap = new HashMap<>();
         argsMap.put(CommonConstant.CORE_IMPLEMENT_DIR_KEY, StringUtils.EMPTY);
         argsMap.put(CommonConstant.CORE_CONFIG_FILE_KEY, StringUtils.EMPTY);