Skip to content

Commit 0e54106

Browse files
committed
[#9653] Add plugin package class requirement filter
1 parent d822a58 commit 0e54106

File tree

12 files changed

+208
-27
lines changed

12 files changed

+208
-27
lines changed

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171

172172
<javax.servlet4.version>4.0.1</javax.servlet4.version>
173173
<javax.servlet.version>3.0.1</javax.servlet.version>
174+
<jakarta.servlet.version>5.0.0</jakarta.servlet.version>
174175

175176

176177
<asm.version>9.4</asm.version>
@@ -1025,6 +1026,12 @@
10251026
<version>${javax.servlet.version}</version>
10261027
<scope>provided</scope>
10271028
</dependency>
1029+
<dependency>
1030+
<groupId>jakarta.servlet</groupId>
1031+
<artifactId>jakarta.servlet-api</artifactId>
1032+
<version>${jakarta.servlet.version}</version>
1033+
<scope>provided</scope>
1034+
</dependency>
10281035

10291036

10301037
<dependency>

profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/classloading/PlainClassLoaderHandler.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.navercorp.pinpoint.profiler.instrument.classloading;
1818

1919
import com.navercorp.pinpoint.common.profiler.concurrent.jsr166.ConcurrentWeakHashMap;
20-
import java.util.Objects;
2120
import com.navercorp.pinpoint.exception.PinpointException;
2221
import com.navercorp.pinpoint.profiler.instrument.classreading.SimpleClassMetadata;
2322
import com.navercorp.pinpoint.profiler.instrument.classreading.SimpleClassMetadataReader;
@@ -27,14 +26,15 @@
2726
import com.navercorp.pinpoint.profiler.util.FileBinary;
2827
import com.navercorp.pinpoint.profiler.util.JarReader;
2928
import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
30-
import org.apache.logging.log4j.Logger;
3129
import org.apache.logging.log4j.LogManager;
30+
import org.apache.logging.log4j.Logger;
3231

3332
import java.io.IOException;
3433
import java.io.InputStream;
3534
import java.util.HashMap;
3635
import java.util.List;
3736
import java.util.Map;
37+
import java.util.Objects;
3838
import java.util.concurrent.ConcurrentHashMap;
3939
import java.util.concurrent.ConcurrentMap;
4040

@@ -107,6 +107,9 @@ private boolean isPluginPackage(String className) {
107107
return pluginConfig.getPluginPackageFilter().accept(className);
108108
}
109109

110+
private boolean meetsRequirement(String className) {
111+
return pluginConfig.getPluginPackageRequirementFilter().accept(className);
112+
}
110113

111114
private Class<?> injectClass0(ClassLoader classLoader, String className) throws IllegalArgumentException {
112115
if (isDebug) {
@@ -133,7 +136,7 @@ private InputStream getPluginInputStream(String classPath) throws IllegalArgumen
133136
}
134137
try {
135138
return pluginJarReader.getInputStream(classPath);
136-
} catch(Exception ex) {
139+
} catch (Exception ex) {
137140
if (isDebug) {
138141
logger.debug("Failed to read plugin jar: {}", pluginConfig.getPluginJarURLExternalForm(), ex);
139142
}
@@ -207,11 +210,12 @@ private void defineJarClass(ClassLoader classLoader, ClassLoaderAttachment attac
207210
Map<String, SimpleClassMetadata> classEntryMap = parse(fileBinaryList);
208211

209212
for (Map.Entry<String, SimpleClassMetadata> entry : classEntryMap.entrySet()) {
210-
211213
final SimpleClassMetadata classMetadata = entry.getValue();
212-
ClassLoadingChecker classLoadingChecker = new ClassLoadingChecker();
213-
classLoadingChecker.isFirstLoad(classMetadata.getClassName());
214-
define0(classLoader, attachment, classMetadata, classEntryMap, classLoadingChecker);
214+
if (meetsRequirement(classMetadata.getClassName())) {
215+
ClassLoadingChecker classLoadingChecker = new ClassLoadingChecker();
216+
classLoadingChecker.isFirstLoad(classMetadata.getClassName());
217+
define0(classLoader, attachment, classMetadata, classEntryMap, classLoadingChecker);
218+
}
215219
}
216220
}
217221

profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/DefaultProfilerPluginContextLoader.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@
1919
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin;
2020
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginGlobalContext;
2121
import com.navercorp.pinpoint.common.trace.ServiceType;
22-
import java.util.Objects;
2322
import com.navercorp.pinpoint.common.util.CodeSourceUtils;
2423
import com.navercorp.pinpoint.profiler.instrument.classloading.ClassInjector;
2524
import com.navercorp.pinpoint.profiler.instrument.classloading.ClassInjectorFactory;
2625
import com.navercorp.pinpoint.profiler.plugin.config.PluginLoadingConfig;
27-
import org.apache.logging.log4j.Logger;
2826
import org.apache.logging.log4j.LogManager;
27+
import org.apache.logging.log4j.Logger;
2928

3029
import java.net.URL;
3130
import java.util.ArrayList;
@@ -34,10 +33,10 @@
3433
import java.util.LinkedHashMap;
3534
import java.util.List;
3635
import java.util.Map;
36+
import java.util.Objects;
3737

3838
/**
3939
* @author Jongho Moon
40-
*
4140
*/
4241
public class DefaultProfilerPluginContextLoader implements ProfilerPluginContextLoader {
4342
private final Logger logger = LogManager.getLogger(getClass());
@@ -85,18 +84,21 @@ public PluginsSetupResult load(List<ProfilerPlugin> profilerPlugins) {
8584

8685
private List<PluginSetupResult> setupPlugin(ProfilerPluginGlobalContext globalContext, JarPlugin<ProfilerPlugin> plugin) {
8786
List<String> pluginPackageList = plugin.getPackageList();
87+
List<String> pluginPackageRequirementList = plugin.getPackageRequirementList();
8888
final ClassNameFilter pluginFilterChain = createPluginFilterChain(pluginPackageList);
89+
final ClassNameFilter pluginPackageRequirementFilter = createPluginRequirementFilterChain(pluginPackageRequirementList);
8990

9091
List<ProfilerPlugin> filterProfilerPlugin = filterProfilerPlugin(plugin.getInstanceList(), pluginLoadingConfig.getDisabledPlugins());
9192

9293
List<PluginSetupResult> result = new ArrayList<>();
9394
for (ProfilerPlugin profilerPlugin : filterProfilerPlugin) {
9495
if (logger.isInfoEnabled()) {
9596
logger.info("{} Plugin {}:{}", profilerPlugin.getClass(), PluginJar.PINPOINT_PLUGIN_PACKAGE, pluginPackageList);
97+
logger.info("{} Requirements {}:{}", profilerPlugin.getClass(), PluginJar.PINPOINT_PLUGIN_PACKAGE_CLASS_REQUIREMENTS, pluginPackageRequirementList);
9698
logger.info("Loading plugin:{} pluginPackage:{}", profilerPlugin.getClass().getName(), profilerPlugin);
9799
}
98100

99-
PluginConfig pluginConfig = new PluginConfig(plugin, pluginFilterChain);
101+
PluginConfig pluginConfig = new PluginConfig(plugin, pluginFilterChain, pluginPackageRequirementFilter);
100102
final ClassInjector classInjector = classInjectorFactory.newClassInjector(pluginConfig);
101103
final PluginSetupResult setupResult = pluginSetup.setupPlugin(globalContext, profilerPlugin, classInjector);
102104
result.add(setupResult);
@@ -129,6 +131,10 @@ private ClassNameFilter createPluginFilterChain(List<String> packageList) {
129131
return filterChain;
130132
}
131133

134+
private ClassNameFilter createPluginRequirementFilterChain(List<String> packageRequirementList) {
135+
return new PluginPackageClassRequirementFilter(packageRequirementList);
136+
}
137+
132138
private static class JarPluginComponents {
133139

134140
private final Logger logger = LogManager.getLogger(this.getClass());
@@ -186,7 +192,7 @@ private void addProfilerPlugin(ProfilerPlugin profilerPlugin) {
186192
}
187193

188194
private JarPlugin<ProfilerPlugin> toJarPlugin() {
189-
return new JarPlugin<>(pluginJar, profilerPlugins, pluginJar.getPluginPackages());
195+
return new JarPlugin<>(pluginJar, profilerPlugins, pluginJar.getPluginPackages(), pluginJar.getPluginPackageRequirements());
190196
}
191197
}
192198
}

profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/JarPlugin.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@
1717
package com.navercorp.pinpoint.profiler.plugin;
1818

1919
import java.net.URL;
20-
import java.util.Objects;
21-
2220
import java.util.List;
21+
import java.util.Objects;
2322
import java.util.jar.JarFile;
2423

2524
/**
@@ -31,11 +30,13 @@ public class JarPlugin<T> implements Plugin<T> {
3130

3231
private final List<T> instanceList;
3332
private final List<String> packageList;
33+
private final List<String> packageRequirementList;
3434

35-
public JarPlugin(PluginJar pluginJar, List<T> instanceList, List<String> packageList) {
35+
public JarPlugin(PluginJar pluginJar, List<T> instanceList, List<String> packageList, List<String> packageRequirementList) {
3636
this.pluginJar = Objects.requireNonNull(pluginJar, "pluginJar");
3737
this.instanceList = Objects.requireNonNull(instanceList, "instanceList");
3838
this.packageList = Objects.requireNonNull(packageList, "packageList");
39+
this.packageRequirementList = Objects.requireNonNull(packageRequirementList, "packageRequirementList");
3940
}
4041

4142
@Override
@@ -53,6 +54,11 @@ public List<String> getPackageList() {
5354
return packageList;
5455
}
5556

57+
@Override
58+
public List<String> getPackageRequirementList() {
59+
return packageRequirementList;
60+
}
61+
5662
public JarFile getJarFile() {
5763
return pluginJar.getJarFile();
5864
}

profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/Plugin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,6 @@ public interface Plugin<T> {
2828
List<T> getInstanceList();
2929

3030
List<String> getPackageList();
31+
32+
List<String> getPackageRequirementList();
3133
}

profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/PluginConfig.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818

1919
import java.net.URL;
2020
import java.util.Objects;
21-
22-
2321
import java.util.jar.JarFile;
2422

2523
/**
@@ -29,12 +27,14 @@ public class PluginConfig {
2927

3028
private final JarPlugin<?> plugin;
3129
private final ClassNameFilter pluginPackageFilter;
30+
private final ClassNameFilter pluginPackageRequirementFilter;
3231

3332
private String pluginJarURLExternalForm;
3433

35-
public PluginConfig(Plugin<?> plugin, ClassNameFilter pluginPackageFilter) {
34+
public PluginConfig(Plugin<?> plugin, ClassNameFilter pluginPackageFilter, ClassNameFilter pluginPackageRequirementFilter) {
3635
this.plugin = cast(plugin);
3736
this.pluginPackageFilter = pluginPackageFilter;
37+
this.pluginPackageRequirementFilter = pluginPackageRequirementFilter;
3838
}
3939

4040
private JarPlugin<?> cast(Plugin<?> plugin) {
@@ -65,6 +65,10 @@ public ClassNameFilter getPluginPackageFilter() {
6565
return pluginPackageFilter;
6666
}
6767

68+
public ClassNameFilter getPluginPackageRequirementFilter() {
69+
return pluginPackageRequirementFilter;
70+
}
71+
6872
@Override
6973
public String toString() {
7074
return "PluginConfig{" +

profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/PluginJar.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@
1717
package com.navercorp.pinpoint.profiler.plugin;
1818

1919
import java.io.File;
20+
import java.io.IOException;
2021
import java.net.MalformedURLException;
2122
import java.net.URL;
22-
import java.util.Objects;
23-
24-
import java.io.IOException;
2523
import java.util.List;
24+
import java.util.Objects;
2625
import java.util.jar.JarFile;
2726

2827
/**
@@ -34,6 +33,7 @@ public class PluginJar {
3433
public static final String PINPOINT_PLUGIN_PACKAGE = "Pinpoint-Plugin-Package";
3534
public static final String PINPOINT_PLUGIN_COMPILER_VERSION = "Pinpoint-Plugin-Compiler-Version";
3635
public static final String DEFAULT_PINPOINT_PLUGIN_PACKAGE_NAME = "com.navercorp.pinpoint.plugin";
36+
public static final String PINPOINT_PLUGIN_PACKAGE_CLASS_REQUIREMENTS = "Pinpoint-Plugin-Package-Class-Requirements";
3737

3838
private final URL url;
3939
private final JarFile jarFile;
@@ -102,6 +102,10 @@ public List<String> getPluginPackages() {
102102
return manifest.getPluginPackages();
103103
}
104104

105+
public List<String> getPluginPackageRequirements() {
106+
return manifest.getPluginPackageRequirements();
107+
}
108+
105109
@Override
106110
public String toString() {
107111
return "PluginJar{" +

profiler/src/main/java/com/navercorp/pinpoint/profiler/plugin/PluginManifest.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ public class PluginManifest {
3131
private final String pluginId;
3232
private final String pluginCompilerVersion;
3333
private final List<String> pluginPackages;
34+
private final List<String> pluginPackageRequirements;
3435

35-
public PluginManifest(String pluginId, String pluginCompilerVersion, List<String> pluginPackages) {
36+
public PluginManifest(String pluginId, String pluginCompilerVersion, List<String> pluginPackages, List<String> pluginPackageRequirements) {
3637
this.pluginId = pluginId;
3738
this.pluginCompilerVersion = pluginCompilerVersion;
3839
this.pluginPackages = pluginPackages;
40+
this.pluginPackageRequirements = pluginPackageRequirements;
3941
}
4042

4143
public static PluginManifest of(JarFile jarFile) {
@@ -45,13 +47,16 @@ public static PluginManifest of(JarFile jarFile) {
4547
final Attributes mainAttributes = manifest.getMainAttributes();
4648

4749
String pluginId = JarFileUtils.getValue(mainAttributes, PluginJar.PINPOINT_PLUGIN_ID, null);
48-
String pluginCompilerVersion = JarFileUtils.getValue(mainAttributes, PluginJar.PINPOINT_PLUGIN_COMPILER_VERSION, null);
50+
String pluginCompilerVersion = JarFileUtils.getValue(mainAttributes, PluginJar.PINPOINT_PLUGIN_COMPILER_VERSION, null);
4951

5052
String pluginPackages = JarFileUtils.getValue(mainAttributes, PluginJar.PINPOINT_PLUGIN_PACKAGE, PluginJar.DEFAULT_PINPOINT_PLUGIN_PACKAGE_NAME);
5153

5254
List<String> pluginPackageList = StringUtils.tokenizeToStringList(pluginPackages, ",");
5355

54-
return new PluginManifest(pluginId, pluginCompilerVersion, pluginPackageList);
56+
String pluginPackageRequirements = JarFileUtils.getValue(mainAttributes, PluginJar.PINPOINT_PLUGIN_PACKAGE_CLASS_REQUIREMENTS, null);
57+
List<String> pluginPackageRequirementList = StringUtils.tokenizeToStringList(pluginPackageRequirements, ",");
58+
59+
return new PluginManifest(pluginId, pluginCompilerVersion, pluginPackageList, pluginPackageRequirementList);
5560
}
5661

5762
private static Manifest getManifest(JarFile jarFile) {
@@ -74,6 +79,10 @@ public List<String> getPluginPackages() {
7479
return pluginPackages;
7580
}
7681

82+
public List<String> getPluginPackageRequirements() {
83+
return pluginPackageRequirements;
84+
}
85+
7786
@Override
7887
public String toString() {
7988
return "PluginManifest{" +
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.navercorp.pinpoint.profiler.plugin;
2+
3+
import org.apache.logging.log4j.LogManager;
4+
import org.apache.logging.log4j.Logger;
5+
6+
import java.util.ArrayList;
7+
import java.util.Arrays;
8+
import java.util.List;
9+
import java.util.Objects;
10+
11+
public class PluginPackageClassRequirementFilter implements ClassNameFilter {
12+
13+
private final String[] packages;
14+
private final String[] requirements;
15+
private final Logger logger = LogManager.getLogger(this.getClass());
16+
17+
public PluginPackageClassRequirementFilter(List<String> packageRequirementList) {
18+
Objects.requireNonNull(packageRequirementList, "packageRequirementList");
19+
20+
final List<String> packageList = new ArrayList<>();
21+
final List<String> requirementList = new ArrayList<>();
22+
parseRequirementList(packageRequirementList, packageList, requirementList);
23+
24+
packages = packageList.toArray(new String[0]);
25+
requirements = requirementList.toArray(new String[0]);
26+
}
27+
28+
@Override
29+
public boolean accept(String className) {
30+
ClassLoader cl = ClassLoader.getSystemClassLoader();
31+
for (int i = 0; i < packages.length; i++) {
32+
if (className.startsWith(packages[i])) {
33+
if (!isLoadedClass(requirements[i], cl)) {
34+
if (logger.isDebugEnabled()) {
35+
logger.debug("reject class:{}, packageName:{}, requirement:{}, classloader:{}", className, packages[i], requirements[i], cl);
36+
}
37+
return REJECT;
38+
}
39+
}
40+
}
41+
return ACCEPT;
42+
}
43+
44+
private boolean isLoadedClass(String classname, ClassLoader cl) {
45+
try {
46+
Class.forName(classname, false, cl);
47+
return true;
48+
} catch (ClassNotFoundException ignored) {
49+
}
50+
return false;
51+
}
52+
53+
private void parseRequirementList(List<String> packageRequirementList, List<String> packageList, List<String> requirementList) {
54+
for (String packageWithRequirement : packageRequirementList) {
55+
String[] split = packageWithRequirement.split(":");
56+
if (split.length == 2) {
57+
packageList.add(split[0]);
58+
requirementList.add(split[1]);
59+
}
60+
}
61+
}
62+
63+
@Override
64+
public String toString() {
65+
return "PluginPackageRequirementFilter{" +
66+
"packages=" + Arrays.toString(packages) +
67+
", requirements=" + Arrays.toString(requirements) +
68+
'}';
69+
}
70+
}

0 commit comments

Comments
 (0)