test: add dubbo integration-test

This commit is contained in:
ReaJason
2026-06-28 21:22:31 +08:00
parent fab736e175
commit a267048ed3
33 changed files with 1780 additions and 5 deletions
+240
View File
@@ -0,0 +1,240 @@
plugins {
id("java")
id("idea")
}
group = "io.github.reajason"
version = rootProject.version
val dubboProviderCommon: SourceSet by sourceSets.creating
val dubboProviderAlibaba: SourceSet by sourceSets.creating
val dubboProviderApache276: SourceSet by sourceSets.creating
val dubboProviderApache277: SourceSet by sourceSets.creating
val dubboProviderApache278: SourceSet by sourceSets.creating
val dubboProviderApache2723: SourceSet by sourceSets.creating
val dubboProviderApache336: SourceSet by sourceSets.creating
val dubboProviderCommonImplementation: Configuration by configurations.getting
val dubboProviderAlibabaImplementation: Configuration by configurations.getting
val dubboProviderApache276Implementation: Configuration by configurations.getting
val dubboProviderApache277Implementation: Configuration by configurations.getting
val dubboProviderApache278Implementation: Configuration by configurations.getting
val dubboProviderApache2723Implementation: Configuration by configurations.getting
val dubboProviderApache336Implementation: Configuration by configurations.getting
val dubboProviderCommonOutput = dubboProviderCommon.output
dubboProviderAlibaba.compileClasspath += dubboProviderCommonOutput
dubboProviderAlibaba.runtimeClasspath += dubboProviderCommonOutput
dubboProviderApache276.compileClasspath += dubboProviderCommonOutput
dubboProviderApache276.runtimeClasspath += dubboProviderCommonOutput
dubboProviderApache277.compileClasspath += dubboProviderCommonOutput
dubboProviderApache277.runtimeClasspath += dubboProviderCommonOutput
dubboProviderApache278.compileClasspath += dubboProviderCommonOutput
dubboProviderApache278.runtimeClasspath += dubboProviderCommonOutput
dubboProviderApache2723.compileClasspath += dubboProviderCommonOutput
dubboProviderApache2723.runtimeClasspath += dubboProviderCommonOutput
dubboProviderApache336.compileClasspath += dubboProviderCommonOutput
dubboProviderApache336.runtimeClasspath += dubboProviderCommonOutput
listOf(
"dubboProviderApache336CompileClasspath",
"dubboProviderApache336RuntimeClasspath"
).forEach { configurationName ->
configurations.named(configurationName) {
exclude(group = "io.netty", module = "netty-transport-native-kqueue")
exclude(group = "io.netty", module = "netty-resolver-dns-native-macos")
}
}
idea {
module {
excludeDirs.add(file("src/main"))
}
}
dependencies {
dubboProviderCommonImplementation("org.slf4j:slf4j-api:1.7.36")
dubboProviderCommonImplementation("org.apache.dubbo:dubbo:2.7.23") {
exclude(group = "log4j", module = "log4j")
}
dubboProviderAlibabaImplementation(dubboProviderCommonOutput)
dubboProviderAlibabaImplementation("com.alibaba:dubbo:2.6.12")
dubboProviderAlibabaImplementation("org.apache.dubbo:dubbo:2.7.6")
dubboProviderAlibabaImplementation("com.alibaba:hessian-lite:3.2.4")
dubboProviderAlibabaImplementation("com.caucho:hessian:4.0.51")
dubboProviderAlibabaImplementation("org.apache.httpcomponents:httpclient:4.5.3")
dubboProviderAlibabaImplementation("org.springframework:spring-web:5.3.39")
dubboProviderAlibabaImplementation("io.netty:netty-all:4.1.25.Final")
dubboProviderAlibabaImplementation("org.mortbay.jetty:jetty:6.1.26")
dubboProviderAlibabaImplementation("org.mortbay.jetty:jetty-util:6.1.26")
dubboProviderAlibabaImplementation("org.slf4j:slf4j-api:1.7.36")
dubboProviderAlibabaImplementation("ch.qos.logback:logback-classic:1.2.13")
fun apacheDubbo27Provider(configuration: Configuration, version: String, tomcatVersion: String) {
add(configuration.name, dubboProviderCommonOutput)
add(configuration.name, "org.apache.dubbo:dubbo:$version") {
exclude(group = "log4j", module = "log4j")
}
add(configuration.name, "com.alibaba:hessian-lite:3.2.4")
add(configuration.name, "com.caucho:hessian:4.0.51")
add(configuration.name, "org.apache.httpcomponents:httpclient:4.5.13")
add(configuration.name, "com.github.briandilley.jsonrpc4j:jsonrpc4j:1.2.0")
add(configuration.name, "org.springframework:spring-web:5.3.39")
add(configuration.name, "org.apache.tomcat.embed:tomcat-embed-core:$tomcatVersion")
add(configuration.name, "org.mortbay.jetty:jetty:6.1.26")
add(configuration.name, "org.mortbay.jetty:jetty-util:6.1.26")
add(configuration.name, "org.slf4j:slf4j-api:1.7.36")
add(configuration.name, "ch.qos.logback:logback-classic:1.2.13")
}
apacheDubbo27Provider(dubboProviderApache276Implementation, "2.7.6", "8.5.100")
apacheDubbo27Provider(dubboProviderApache277Implementation, "2.7.7", "8.5.100")
apacheDubbo27Provider(dubboProviderApache278Implementation, "2.7.8", "9.0.104")
apacheDubbo27Provider(dubboProviderApache2723Implementation, "2.7.23", "9.0.104")
dubboProviderApache336Implementation(dubboProviderCommonOutput)
dubboProviderApache336Implementation("org.apache.dubbo:dubbo:3.3.6") {
exclude(group = "log4j", module = "log4j")
}
dubboProviderApache336Implementation("org.apache.dubbo:dubbo-rpc-triple:3.3.6")
dubboProviderApache336Implementation("org.apache.dubbo.extensions:dubbo-rpc-http:3.3.1")
dubboProviderApache336Implementation("org.apache.dubbo.extensions:dubbo-rpc-hessian:3.3.0")
dubboProviderApache336Implementation("org.apache.dubbo:dubbo-remoting-http:3.3.0-beta.2")
dubboProviderApache336Implementation("com.caucho:hessian:4.0.51")
dubboProviderApache336Implementation("io.netty:netty-all:4.1.119.Final")
dubboProviderApache336Implementation("org.slf4j:slf4j-api:2.0.17")
dubboProviderApache336Implementation("ch.qos.logback:logback-classic:1.5.18")
}
tasks.named<JavaCompile>(dubboProviderCommon.compileJavaTaskName) {
options.release.set(8)
}
listOf(
dubboProviderAlibaba,
dubboProviderApache276,
dubboProviderApache277,
dubboProviderApache278,
dubboProviderApache2723,
dubboProviderApache336
).forEach { sourceSet ->
tasks.named<JavaCompile>(sourceSet.compileJavaTaskName) {
options.release.set(8)
}
}
fun registerDubboFatJar(
taskName: String,
sourceSet: SourceSet,
mainClassName: String,
mergeApacheProtocolSpi: Boolean = false
): TaskProvider<Jar> {
val protocolSpiPath = "META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol"
val mergedProtocolSpi = layout.buildDirectory.file("generated/$taskName/$protocolSpiPath")
val mergeTask = if (mergeApacheProtocolSpi) {
tasks.register("${taskName}MergeProtocolSpi") {
inputs.files(sourceSet.runtimeClasspath)
outputs.file(mergedProtocolSpi)
doLast {
val outputFile = mergedProtocolSpi.get().asFile
outputFile.parentFile.mkdirs()
val mergedLines = linkedSetOf<String>()
sourceSet.runtimeClasspath.files
.filter { it.extension == "jar" }
.forEach { runtimeJar ->
zipTree(runtimeJar).matching {
include(protocolSpiPath)
}.forEach { spiFile ->
spiFile.readLines()
.map(String::trim)
.filter { it.isNotEmpty() && !it.startsWith("#") }
.forEach(mergedLines::add)
}
}
outputFile.writeText(mergedLines.joinToString(System.lineSeparator()))
}
}
} else {
null
}
return tasks.register<Jar>(taskName) {
group = "verification"
archiveClassifier.set(taskName.removePrefix("dubbo").removeSuffix("FatJar").lowercase())
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
dependsOn(sourceSet.classesTaskName, dubboProviderCommon.classesTaskName)
manifest {
attributes["Main-Class"] = mainClassName
}
from(sourceSet.output)
from(dubboProviderCommon.output)
if (mergeApacheProtocolSpi) {
dependsOn(mergeTask)
from({
sourceSet.runtimeClasspath.files
.filter { it.exists() }
.map { if (it.isDirectory) it else zipTree(it) }
}) {
includeEmptyDirs = false
exclude(protocolSpiPath)
}
into("META-INF/dubbo/internal") {
from(mergedProtocolSpi) {
rename { "org.apache.dubbo.rpc.Protocol" }
}
}
} else {
from({
sourceSet.runtimeClasspath.files
.filter { it.exists() }
.map { if (it.isDirectory) it else zipTree(it) }
})
}
}
}
val dubboAlibabaProviderFatJar = registerDubboFatJar(
"dubboAlibabaProviderFatJar",
dubboProviderAlibaba,
"io.github.reajason.dubbo.fixture.alibaba.AlibabaDubbo2Provider"
)
val dubboApache276ProviderFatJar = registerDubboFatJar(
"dubboApache276ProviderFatJar",
dubboProviderApache276,
"io.github.reajason.dubbo.fixture.apache2.ApacheDubbo276Provider"
)
val dubboApache277ProviderFatJar = registerDubboFatJar(
"dubboApache277ProviderFatJar",
dubboProviderApache277,
"io.github.reajason.dubbo.fixture.apache2.ApacheDubbo277Provider"
)
val dubboApache278ProviderFatJar = registerDubboFatJar(
"dubboApache278ProviderFatJar",
dubboProviderApache278,
"io.github.reajason.dubbo.fixture.apache2.ApacheDubbo278Provider"
)
val dubboApache2723ProviderFatJar = registerDubboFatJar(
"dubboApache2723ProviderFatJar",
dubboProviderApache2723,
"io.github.reajason.dubbo.fixture.apache2.ApacheDubbo2723Provider"
)
val dubboApache336ProviderFatJar = registerDubboFatJar(
"dubboApache336ProviderFatJar",
dubboProviderApache336,
"io.github.reajason.dubbo.fixture.apache3.ApacheDubbo336Provider",
mergeApacheProtocolSpi = true
)
tasks.register("dubboProviderFatJars") {
group = "verification"
dependsOn(
dubboAlibabaProviderFatJar,
dubboApache276ProviderFatJar,
dubboApache277ProviderFatJar,
dubboApache278ProviderFatJar,
dubboApache2723ProviderFatJar,
dubboApache336ProviderFatJar
)
}
@@ -0,0 +1,65 @@
package io.github.reajason.dubbo.fixture.alibaba;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
import io.github.reajason.dubbo.fixture.api.BytecodeLoadingService;
import io.github.reajason.dubbo.fixture.api.DemoService;
import io.github.reajason.dubbo.fixture.common.BytecodeLoadingServiceImpl;
import io.github.reajason.dubbo.fixture.common.DemoServiceImpl;
import io.github.reajason.dubbo.fixture.common.LoadBytesExportContext;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
public class AlibabaDubbo2Provider {
public static void main(String[] args) throws InterruptedException {
System.setProperty("dubbo.compiler", "jdk");
ApplicationConfig application = new ApplicationConfig("alibaba-dubbo2-provider");
application.setQosEnable(true);
application.setQosPort(22221);
ProtocolConfig dubboProtocol = new ProtocolConfig();
dubboProtocol.setName("dubbo");
dubboProtocol.setPort(20880);
ProtocolConfig hessianProtocol = new ProtocolConfig();
hessianProtocol.setName("hessian");
hessianProtocol.setPort(28080);
ProtocolConfig httpProtocol = new ProtocolConfig();
httpProtocol.setName("http");
httpProtocol.setPort(28081);
RegistryConfig registry = new RegistryConfig("N/A");
LoadBytesExportContext.register(application, registry, Arrays.asList(dubboProtocol, hessianProtocol, httpProtocol));
ServiceConfig<DemoService> demoService = new ServiceConfig<DemoService>();
demoService.setApplication(application);
demoService.setRegistry(registry);
demoService.setProtocols(Arrays.asList(dubboProtocol, hessianProtocol, httpProtocol));
demoService.setInterface(DemoService.class);
demoService.setRef(new DemoServiceImpl("alibaba-dubbo-2.6.12"));
demoService.export();
ServiceConfig<BytecodeLoadingService> loaderService = new ServiceConfig<BytecodeLoadingService>();
loaderService.setApplication(application);
loaderService.setRegistry(registry);
loaderService.setProtocols(Arrays.asList(dubboProtocol, hessianProtocol, httpProtocol));
loaderService.setInterface(BytecodeLoadingService.class);
loaderService.setRef(new BytecodeLoadingServiceImpl());
loaderService.export();
System.out.println("==============================================");
System.out.println(" alibaba-dubbo 2.6.12 Provider started");
System.out.println(" dubbo -> dubbo://127.0.0.1:20880");
System.out.println(" hessian -> hessian://127.0.0.1:28080");
System.out.println(" http -> http://127.0.0.1:28081");
System.out.println(" qos -> 127.0.0.1:22221");
System.out.println("==============================================");
new CountDownLatch(1).await();
}
}
@@ -0,0 +1,7 @@
package io.github.reajason.dubbo.fixture.apache2;
public class ApacheDubbo2723Provider {
public static void main(String[] args) throws InterruptedException {
ApacheDubbo2Provider.start("apache-dubbo-2.7.23", 20881, 28082, 28083, 22222);
}
}
@@ -0,0 +1,7 @@
package io.github.reajason.dubbo.fixture.apache2;
public class ApacheDubbo276Provider {
public static void main(String[] args) throws InterruptedException {
ApacheDubbo2Provider.start("apache-dubbo-2.7.6", 20885, 28086, 28087, 22226);
}
}
@@ -0,0 +1,7 @@
package io.github.reajason.dubbo.fixture.apache2;
public class ApacheDubbo277Provider {
public static void main(String[] args) throws InterruptedException {
ApacheDubbo2Provider.start("apache-dubbo-2.7.7", 20886, 28088, 28089, 22227);
}
}
@@ -0,0 +1,7 @@
package io.github.reajason.dubbo.fixture.apache2;
public class ApacheDubbo278Provider {
public static void main(String[] args) throws InterruptedException {
ApacheDubbo2Provider.start("apache-dubbo-2.7.8", 20887, 28090, 28091, 22228);
}
}
@@ -0,0 +1,65 @@
package io.github.reajason.dubbo.fixture.apache3;
import io.github.reajason.dubbo.fixture.api.BytecodeLoadingService;
import io.github.reajason.dubbo.fixture.api.DemoService;
import io.github.reajason.dubbo.fixture.common.BytecodeLoadingServiceImpl;
import io.github.reajason.dubbo.fixture.common.DemoServiceImpl;
import io.github.reajason.dubbo.fixture.common.LoadBytesExportContext;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import java.util.Arrays;
public class ApacheDubbo336Provider {
public static void main(String[] args) {
System.setProperty("dubbo.compiler", "jdk");
ApplicationConfig application = new ApplicationConfig("apache-dubbo-3.3.6-provider");
application.setQosEnable(true);
application.setQosPort(22223);
RegistryConfig registry = new RegistryConfig("N/A");
ProtocolConfig dubboProtocol = new ProtocolConfig("dubbo", 20882);
ProtocolConfig triProtocol = new ProtocolConfig("tri", 50051);
ProtocolConfig hessianProtocol = new ProtocolConfig("hessian", 28084);
ProtocolConfig httpProtocol = new ProtocolConfig("http", 28085);
LoadBytesExportContext.register(
application,
registry,
Arrays.asList(dubboProtocol, triProtocol, hessianProtocol, httpProtocol)
);
ServiceConfig<DemoService> demoService = new ServiceConfig<DemoService>();
demoService.setInterface(DemoService.class);
demoService.setRef(new DemoServiceImpl("apache-dubbo-3.3.6"));
ServiceConfig<BytecodeLoadingService> loaderService = new ServiceConfig<BytecodeLoadingService>();
loaderService.setInterface(BytecodeLoadingService.class);
loaderService.setRef(new BytecodeLoadingServiceImpl());
DubboBootstrap.getInstance()
.application(application)
.registry(registry)
.protocol(dubboProtocol)
.protocol(triProtocol)
.protocol(hessianProtocol)
.protocol(httpProtocol)
.service(demoService)
.service(loaderService)
.start();
System.out.println("==============================================");
System.out.println(" apache-dubbo-3.3.6 Provider started");
System.out.println(" dubbo -> dubbo://127.0.0.1:20882");
System.out.println(" tri -> tri://127.0.0.1:50051");
System.out.println(" hessian -> hessian://127.0.0.1:28084");
System.out.println(" http -> http://127.0.0.1:28085");
System.out.println(" qos -> 127.0.0.1:22223");
System.out.println("==============================================");
DubboBootstrap.getInstance().await();
}
}
@@ -0,0 +1,71 @@
package io.github.reajason.dubbo.fixture.apache2;
import io.github.reajason.dubbo.fixture.api.BytecodeLoadingService;
import io.github.reajason.dubbo.fixture.api.DemoService;
import io.github.reajason.dubbo.fixture.common.BytecodeLoadingServiceImpl;
import io.github.reajason.dubbo.fixture.common.DemoServiceImpl;
import io.github.reajason.dubbo.fixture.common.LoadBytesExportContext;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
public final class ApacheDubbo2Provider {
private ApacheDubbo2Provider() {
}
public static void start(String providerName, int dubboPort, int hessianPort, int httpPort, int qosPort)
throws InterruptedException {
System.setProperty("dubbo.compiler", "jdk");
ApplicationConfig application = new ApplicationConfig(providerName + "-provider");
application.setQosEnable(true);
application.setQosPort(qosPort);
ProtocolConfig dubboProtocol = new ProtocolConfig();
dubboProtocol.setName("dubbo");
dubboProtocol.setPort(dubboPort);
ProtocolConfig hessianProtocol = new ProtocolConfig();
hessianProtocol.setName("hessian");
hessianProtocol.setPort(hessianPort);
hessianProtocol.setServer("tomcat");
ProtocolConfig httpProtocol = new ProtocolConfig();
httpProtocol.setName("http");
httpProtocol.setPort(httpPort);
httpProtocol.setServer("tomcat");
RegistryConfig registry = new RegistryConfig("N/A");
LoadBytesExportContext.register(application, registry, Arrays.asList(dubboProtocol, hessianProtocol, httpProtocol));
ServiceConfig<DemoService> demoService = new ServiceConfig<DemoService>();
demoService.setApplication(application);
demoService.setRegistry(registry);
demoService.setProtocols(Arrays.asList(dubboProtocol, hessianProtocol, httpProtocol));
demoService.setInterface(DemoService.class);
demoService.setRef(new DemoServiceImpl(providerName));
demoService.export();
ServiceConfig<BytecodeLoadingService> loaderService = new ServiceConfig<BytecodeLoadingService>();
loaderService.setApplication(application);
loaderService.setRegistry(registry);
loaderService.setProtocols(Arrays.asList(dubboProtocol, hessianProtocol, httpProtocol));
loaderService.setInterface(BytecodeLoadingService.class);
loaderService.setRef(new BytecodeLoadingServiceImpl());
loaderService.export();
System.out.println("==============================================");
System.out.println(" " + providerName + " Provider started");
System.out.println(" dubbo -> dubbo://127.0.0.1:" + dubboPort);
System.out.println(" hessian -> hessian://127.0.0.1:" + hessianPort);
System.out.println(" http -> http://127.0.0.1:" + httpPort);
System.out.println(" qos -> 127.0.0.1:" + qosPort);
System.out.println("==============================================");
new CountDownLatch(1).await();
}
}
@@ -0,0 +1,5 @@
package io.github.reajason.dubbo.fixture.api;
public interface BytecodeLoadingService {
String loadBytes(String base64);
}
@@ -0,0 +1,5 @@
package io.github.reajason.dubbo.fixture.api;
public interface DemoService {
String sayHello(String name);
}
@@ -0,0 +1,11 @@
package io.github.reajason.dubbo.fixture.common;
import io.github.reajason.dubbo.fixture.api.BytecodeLoadingService;
public class BytecodeLoadingServiceImpl implements BytecodeLoadingService {
@Override
public String loadBytes(String base64) {
return BytecodeLoadingSupport.loadBase64(base64);
}
}
@@ -0,0 +1,246 @@
package io.github.reajason.dubbo.fixture.common;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
public final class BytecodeLoadingSupport {
private BytecodeLoadingSupport() {
}
public static String loadBase64(String base64) {
String normalized = normalizeBase64(base64);
byte[] bytes = Base64.getMimeDecoder().decode(normalized);
return loadClassBytes(bytes);
}
public static String loadClassBytes(byte[] bytes) {
requireClassBytes(bytes);
try {
return new PayloadClassLoader(hostClassLoader()).defineAndInstantiate(bytes);
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("failed to load bytecode payload", e);
}
}
private static String normalizeBase64(String base64) {
if (base64 == null) {
throw new IllegalArgumentException("base64 must not be null");
}
String trimmed = base64.trim();
if (trimmed.isEmpty()) {
throw new IllegalArgumentException("base64 must not be blank");
}
return trimmed;
}
private static void requireClassBytes(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
throw new IllegalArgumentException("class bytes must not be empty");
}
}
private static ClassLoader hostClassLoader() {
ClassLoader classLoader = BytecodeLoadingSupport.class.getClassLoader();
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
}
return classLoader;
}
public static Class<?> defineIntoHostClassLoader(String className, byte[] bytes) {
if (className == null || className.trim().isEmpty()) {
throw new IllegalArgumentException("class name must not be blank");
}
requireClassBytes(bytes);
ClassLoader classLoader = hostClassLoader();
Class<?> loadedClass = findLoadedClass(className, classLoader);
if (loadedClass != null) {
return loadedClass;
}
try {
return defineClass(className, bytes, classLoader);
} catch (LinkageError e) {
loadedClass = findLoadedClass(className, classLoader);
if (loadedClass != null) {
return loadedClass;
}
throw e;
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("failed to define class in host class loader: " + className, e);
}
}
public static void registerWithDubboClassPool(String className, byte[] bytes) {
if (className == null || className.trim().isEmpty() || bytes == null || bytes.length == 0) {
return;
}
Class<?> classPoolClass = null;
List<Object> classPools = new ArrayList<Object>();
try {
classPoolClass = Class.forName("javassist.ClassPool", false, hostClassLoader());
classPools.add(classPoolClass.getMethod("getDefault").invoke(null));
classPools.addAll(dubboClassGeneratorPools());
for (Object classPool : classPools) {
if (classPoolContains(classPoolClass, classPool, className)) {
continue;
}
Method makeClass = classPoolClass.getMethod("makeClass", InputStream.class);
makeClass.invoke(classPool, new ByteArrayInputStream(bytes));
}
} catch (ClassNotFoundException ignored) {
// Javassist is not present for all clients.
} catch (InvocationTargetException e) {
if (classPoolClass != null && anyClassPoolContains(classPoolClass, classPools, className)) {
return;
}
throw new IllegalStateException("failed to register class with Dubbo Javassist pool: " + className, e.getCause());
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("failed to register class with Dubbo Javassist pool: " + className, e);
}
}
private static Class<?> findLoadedClass(String className, ClassLoader classLoader) {
try {
return Class.forName(className, false, classLoader);
} catch (ClassNotFoundException e) {
return null;
}
}
private static Class<?> defineClass(String className, byte[] bytes, ClassLoader classLoader)
throws ReflectiveOperationException {
Method defineClass = ClassLoader.class.getDeclaredMethod(
"defineClass",
String.class,
byte[].class,
int.class,
int.class,
ProtectionDomain.class
);
defineClass.setAccessible(true);
try {
return (Class<?>) defineClass.invoke(
classLoader,
className,
bytes,
0,
bytes.length,
BytecodeLoadingSupport.class.getProtectionDomain()
);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof LinkageError) {
throw (LinkageError) cause;
}
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
if (cause instanceof Error) {
throw (Error) cause;
}
throw e;
}
}
private static List<Object> dubboClassGeneratorPools() {
List<Object> classPools = new ArrayList<Object>();
List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
addClassLoader(classLoaders, hostClassLoader());
addClassLoader(classLoaders, Thread.currentThread().getContextClassLoader());
for (ClassLoader classLoader : classLoaders) {
addDubboClassGeneratorPool(classPools, "com.alibaba.dubbo.common.bytecode.ClassGenerator", classLoader);
addDubboClassGeneratorPool(classPools, "org.apache.dubbo.common.bytecode.ClassGenerator", classLoader);
}
return classPools;
}
private static void addClassLoader(List<ClassLoader> classLoaders, ClassLoader classLoader) {
if (classLoader != null && !classLoaders.contains(classLoader)) {
classLoaders.add(classLoader);
}
}
private static void addDubboClassGeneratorPool(List<Object> classPools, String className, ClassLoader classLoader) {
try {
Class<?> classGeneratorClass = Class.forName(className, false, hostClassLoader());
Method getClassPool = classGeneratorClass.getMethod("getClassPool", ClassLoader.class);
Object classPool = getClassPool.invoke(null, classLoader);
if (classPool != null && !classPools.contains(classPool)) {
classPools.add(classPool);
}
} catch (ClassNotFoundException ignored) {
// This runtime is using the other Dubbo namespace.
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("failed to resolve Dubbo class pool from " + className, e);
}
}
private static boolean anyClassPoolContains(Class<?> classPoolClass, List<Object> classPools, String className) {
for (Object classPool : classPools) {
try {
if (classPoolContains(classPoolClass, classPool, className)) {
return true;
}
} catch (ReflectiveOperationException ignored) {
}
}
return false;
}
private static boolean classPoolContains(Class<?> classPoolClass, Object classPool, String className)
throws ReflectiveOperationException {
try {
Method getOrNull = classPoolClass.getMethod("getOrNull", String.class);
return getOrNull.invoke(classPool, className) != null;
} catch (NoSuchMethodException e) {
try {
Method get = classPoolClass.getMethod("get", String.class);
return get.invoke(classPool, className) != null;
} catch (InvocationTargetException invocationTargetException) {
Throwable cause = invocationTargetException.getCause();
if (cause != null && "javassist.NotFoundException".equals(cause.getClass().getName())) {
return false;
}
throw invocationTargetException;
}
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause != null && "javassist.NotFoundException".equals(cause.getClass().getName())) {
return false;
}
throw e;
}
}
private static final class PayloadClassLoader extends ClassLoader {
private PayloadClassLoader(ClassLoader parent) {
super(parent);
}
private String defineAndInstantiate(byte[] bytes) throws ReflectiveOperationException {
Thread thread = Thread.currentThread();
ClassLoader original = thread.getContextClassLoader();
thread.setContextClassLoader(this);
try {
Object instance = defineClass(bytes, 0, bytes.length).newInstance();
return String.valueOf(instance);
} finally {
thread.setContextClassLoader(original);
}
}
}
}
@@ -0,0 +1,17 @@
package io.github.reajason.dubbo.fixture.common;
import io.github.reajason.dubbo.fixture.api.DemoService;
public class DemoServiceImpl implements DemoService {
private final String providerName;
public DemoServiceImpl(String providerName) {
this.providerName = providerName;
}
@Override
public String sayHello(String name) {
return "Hello, " + name + " from " + providerName;
}
}
@@ -0,0 +1,31 @@
package io.github.reajason.dubbo.fixture.common;
import java.util.List;
public final class LoadBytesExportContext {
private static volatile Object application;
private static volatile Object registry;
private static volatile List<?> protocols;
private LoadBytesExportContext() {
}
public static void register(Object applicationConfig, Object registryConfig, List<?> protocolConfigs) {
application = applicationConfig;
registry = registryConfig;
protocols = protocolConfigs;
}
public static Object application() {
return application;
}
public static Object registry() {
return registry;
}
public static List<?> protocols() {
return protocols;
}
}
@@ -0,0 +1,6 @@
package io.github.reajason.dubbo.fixture.common;
public final class Noop {
private Noop() {
}
}