diff --git a/koupleless-build-plugin/koupleless-base-build-plugin/pom.xml b/koupleless-build-plugin/koupleless-base-build-plugin/pom.xml
new file mode 100644
index 000000000..c01ec10d9
--- /dev/null
+++ b/koupleless-build-plugin/koupleless-base-build-plugin/pom.xml
@@ -0,0 +1,102 @@
+
+
+ 4.0.0
+
+ com.alipay.sofa.koupleless
+ koupleless-build-plugin
+ ${revision}
+ ../pom.xml
+
+
+ koupleless-base-build-plugin
+ ${revision}
+ maven-plugin
+
+
+
+
+ org.apache.maven
+ maven-plugin-api
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+
+
+ org.apache.maven
+ maven-aether-provider
+
+
+ org.apache.maven
+ maven-core
+
+
+ org.apache.maven
+ maven-project
+
+
+ com.google.guava
+ guava
+
+
+ org.projectlombok
+ lombok
+ compile
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ compile
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+
+
+ org.apache.commons
+ commons-collections4
+
+
+ junit
+ junit
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+
+
+
+
+ src/main/resources
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-plugin-plugin
+ 3.5
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.3
+
+
+ 8
+
+
+
+
+
+
\ No newline at end of file
diff --git a/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java
new file mode 100644
index 000000000..c452ea00c
--- /dev/null
+++ b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.koupleless.base.build.plugin;
+
+/*
+ * Copyright 2001-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import com.alipay.sofa.koupleless.base.build.plugin.common.JarFileUtils;
+import com.alipay.sofa.koupleless.base.build.plugin.model.KouplelessAdapterConfig;
+import com.alipay.sofa.koupleless.base.build.plugin.model.MavenDependencyAdapterMapping;
+import com.alipay.sofa.koupleless.base.build.plugin.model.MavenDependencyMatcher;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import com.google.common.base.Preconditions;
+import lombok.SneakyThrows;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.resolution.ArtifactRequest;
+import org.eclipse.aether.resolution.ArtifactResult;
+
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * Goal which touches a timestamp file.
+ *
+ * @goal touch
+ * @phase process-sources
+ */
+@Mojo(name = "add-patch", defaultPhase = LifecyclePhase.PROCESS_CLASSES)
+public class KouplelessBaseBuildPrePackageMojo extends AbstractMojo {
+
+ @Parameter(defaultValue = "${project.build.directory}", readonly = true)
+ File outputDirectory;
+
+ @Parameter(defaultValue = "${project}", required = true, readonly = true)
+ MavenProject project;
+
+ @Parameter(defaultValue = "${session}", required = true, readonly = true)
+ MavenSession session;
+
+ @Component
+ RepositorySystem repositorySystem;
+
+ private ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());
+
+ KouplelessAdapterConfig kouplelessAdapterConfig;
+
+ String defaultGroupId = "";
+ String defaultVersion = "";
+
+ void initKouplelessAdapterConfig() throws Exception {
+ if (kouplelessAdapterConfig == null) {
+ InputStream mappingConfigIS = this.getClass().getClassLoader()
+ .getResourceAsStream("adapter-mapping.yaml");
+
+ kouplelessAdapterConfig = yamlMapper.readValue(mappingConfigIS,
+ KouplelessAdapterConfig.class);
+
+ for (MavenDependencyAdapterMapping mappings : CollectionUtils
+ .emptyIfNull(kouplelessAdapterConfig.getAdapterMappings())) {
+
+ }
+ }
+
+ Properties properties = new Properties();
+ properties.load(getClass().getClassLoader().getResourceAsStream("project.properties"));
+ defaultGroupId = properties.getProperty("project.groupId");
+ defaultVersion = properties.getProperty("project.version");
+ }
+
+ String getDependencyId(Dependency dependency) {
+ return dependency.getGroupId() + ":" + dependency.getArtifactId() + ":"
+ + dependency.getVersion() + ":" + dependency.getType()
+ + (dependency.getClassifier() != null ? ":" + dependency.getClassifier() : "");
+ }
+
+ // visible for testing
+ List getDependenciesToAdd() {
+ List adapterDependencies = new ArrayList<>();
+ if (kouplelessAdapterConfig == null) {
+ getLog().info("kouplelessAdapterConfig is null, skip adding dependencies.");
+ return adapterDependencies;
+ }
+
+ if (kouplelessAdapterConfig.getCommonDependencies() != null) {
+ adapterDependencies.addAll(kouplelessAdapterConfig.getCommonDependencies());
+ }
+
+ Collection adapterMappings = CollectionUtils
+ .emptyIfNull(kouplelessAdapterConfig.getAdapterMappings());
+ for (MavenDependencyAdapterMapping adapterMapping : adapterMappings) {
+ MavenDependencyMatcher matcher = adapterMapping.getMatcher();
+
+ if (matcher != null && matcher.getRegexp() != null) {
+ String regexp = matcher.getRegexp();
+ for (Dependency dependency : project.getDependencies()) {
+ String dependencyId = getDependencyId(dependency);
+ if (Pattern.compile(regexp).matcher(dependencyId).matches()) {
+ adapterDependencies.add(adapterMapping.getAdapter());
+ }
+ }
+ }
+
+ }
+ return adapterDependencies;
+ }
+
+ void addDependenciesDynamically() {
+ if (kouplelessAdapterConfig == null) {
+ getLog().info("kouplelessAdapterConfig is null, skip adding dependencies.");
+ return;
+ }
+
+ Collection dependencies = getDependenciesToAdd();
+ for (Dependency dependency : dependencies) {
+ try {
+ if (StringUtils.isBlank(dependency.getVersion())) {
+ dependency.setVersion(defaultVersion);
+ }
+ if (StringUtils.isBlank(dependency.getGroupId())) {
+ dependency.setGroupId(defaultGroupId);
+ }
+ getLog().debug("start downloading dependency: " + dependency.toString());
+ Artifact artifact = downloadAdapterDependency(dependency);
+ getLog().debug("start add dependency to project root: " + dependency.toString());
+ addArtifactToProjectRoot(artifact);
+ getLog().info("success add dependency: " + dependency.toString());
+ } catch (Throwable t) {
+ getLog().error("error add dependency: " + dependency.toString(), t);
+ }
+ }
+ }
+
+ Artifact downloadAdapterDependency(Dependency dependency) {
+ DefaultArtifact patchArtifact = new DefaultArtifact(dependency.getGroupId() + ":"
+ + dependency.getArtifactId() + ":"
+ + dependency.getVersion());
+
+ try {
+ ArtifactRequest artifactRequest = new ArtifactRequest().setArtifact(patchArtifact)
+ .setRepositories(project.getRemoteProjectRepositories());
+
+ ArtifactResult artifactResult = repositorySystem.resolveArtifact(
+ session.getRepositorySession(), artifactRequest);
+
+ Preconditions.checkState(artifactResult.isResolved(), "artifact not resolved.");
+ return artifactResult.getArtifact();
+ } catch (Throwable t) {
+ getLog().error(t);
+ throw new RuntimeException(t);
+ }
+ }
+
+ void addArtifactToProjectRoot(Artifact artifact) {
+ File file = artifact.getFile();
+ Map entryToContent = JarFileUtils.getFileContentAsLines(file,
+ Pattern.compile(".*\\.class$"));
+ for (Map.Entry entry : entryToContent.entrySet()) {
+ addPatchToProjectRoot(entry.getKey(), entry.getValue());
+ }
+ }
+
+ @SneakyThrows
+ void addPatchToProjectRoot(String entryName, Byte[] bytes) {
+ Path outputfile = Paths.get(outputDirectory.getAbsolutePath(), "classes", entryName);
+ Path parentDir = outputfile.getParent();
+ byte[] primitiveByte = new byte[bytes.length];
+ for (int i = 0; i < bytes.length; i++) {
+ primitiveByte[i] = bytes[i];
+ }
+ Files.createDirectories(parentDir);
+ Files.write(outputfile, primitiveByte);
+ }
+
+ @Override
+ public void execute() throws MojoExecutionException {
+ try {
+ initKouplelessAdapterConfig();
+ addDependenciesDynamically();
+ } catch (Throwable t) {
+ getLog().error(t);
+ throw new RuntimeException(t);
+ }
+ }
+}
diff --git a/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/common/JarFileUtils.java b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/common/JarFileUtils.java
new file mode 100644
index 000000000..f697cbcc8
--- /dev/null
+++ b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/common/JarFileUtils.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.koupleless.base.build.plugin.common;
+
+import lombok.SneakyThrows;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.regex.Pattern;
+
+/**
+ * jar file utils
+ *
+ * @author CodeNoobKing
+ */
+public class JarFileUtils {
+
+ /**
+ * get content as file lines inside a bundled jar file.
+ *
+ * @param file jarfile
+ * @param entryPattern the target file.
+ * @return the content as list of string.
+ */
+ @SneakyThrows
+ public static Map getFileContentAsLines(File file, Pattern entryPattern) {
+ Map result = new HashMap<>();
+ try (JarInputStream jin = new JarInputStream(new FileInputStream(file))) {
+
+ JarEntry entry = null;
+ while ((entry = jin.getNextJarEntry()) != null) {
+ if (!entryPattern.matcher(entry.getName()).matches() || entry.isDirectory()) {
+ continue;
+ }
+
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ int nRead = -1;
+ byte[] data = new byte[1024];
+ while ((nRead = jin.read(data, 0, data.length)) != -1) {
+ buffer.write(data, 0, nRead);
+ }
+
+ byte[] byteArray = buffer.toByteArray();
+ Byte[] boxing = new Byte[byteArray.length];
+ for (int i = 0; i < byteArray.length; i++) {
+ boxing[i] = byteArray[i];
+ }
+ result.put(entry.getName(), boxing);
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfig.java b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfig.java
new file mode 100644
index 000000000..719119432
--- /dev/null
+++ b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfig.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.koupleless.base.build.plugin.model;
+
+import lombok.*;
+import org.apache.maven.model.Dependency;
+
+import java.util.List;
+
+/**
+ * @author CodeNoobKing
+ * @date 2024/2/6
+ */
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@Data
+public class KouplelessAdapterConfig {
+
+ /**
+ * 存在一些通用的依赖,需要用户引入。
+ */
+ List commonDependencies;
+
+ /**
+ * 适配的依赖。
+ */
+ List adapterMappings;
+}
diff --git a/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyAdapterMapping.java b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyAdapterMapping.java
new file mode 100644
index 000000000..5cb44f538
--- /dev/null
+++ b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyAdapterMapping.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.koupleless.base.build.plugin.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.maven.model.Dependency;
+
+/**
+ * @author CodeNoobKing
+ * @date 2024/2/6
+ */
+@NoArgsConstructor
+@AllArgsConstructor
+@Data
+@Builder
+public class MavenDependencyAdapterMapping {
+ /**
+ * 匹配用户的以来。
+ */
+ private MavenDependencyMatcher matcher;
+
+ /**
+ * 适配的依赖。
+ */
+ private Dependency adapter;
+}
diff --git a/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyMatcher.java b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyMatcher.java
new file mode 100644
index 000000000..b9c8cc041
--- /dev/null
+++ b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyMatcher.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.koupleless.base.build.plugin.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author CodeNoobKing
+ * @date 2024/2/6
+ */
+@NoArgsConstructor
+@AllArgsConstructor
+@Data
+@Builder
+public class MavenDependencyMatcher {
+ /**
+ * 用正则表达式匹配用户的依赖。
+ */
+ private String regexp;
+}
diff --git a/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping.yaml b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping.yaml
new file mode 100644
index 000000000..9afe4e606
--- /dev/null
+++ b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping.yaml
@@ -0,0 +1,17 @@
+adapterMappings:
+ - matcher:
+ regexp: ".*com\\.ctrip\\.framework\\.apollo:apollo-client.*"
+ adapter:
+ artifactId: koupleless-adapter-apollo
+ - matcher:
+ regexp: ".*(com\\.alibaba:dubbo-dependencies-bom:2\\.6|com\\.alibaba:dubbo:2\\.6).*"
+ adapter:
+ artifactId: koupleless-adapter-dubbo2.6
+ - matcher:
+ regexp: ".*spring-boot-starter-log4j2:(?!2\\.1).*"
+ adapter:
+ artifactId: koupleless-adapter-log4j2
+ - matcher:
+ regexp: ".*spring-boot-starter-log4j2:2\\.1.*"
+ adapter:
+ artifactId: koupleless-adapter-log4j2-springboot2.1.9
diff --git a/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/project.properties b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/project.properties
new file mode 100644
index 000000000..76bf73291
--- /dev/null
+++ b/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/project.properties
@@ -0,0 +1,2 @@
+project.groupId=${project.groupId}
+project.version=${project.version}
\ No newline at end of file
diff --git a/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojoTest.java b/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojoTest.java
new file mode 100644
index 000000000..954b92440
--- /dev/null
+++ b/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojoTest.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.koupleless.base.build.plugin;
+
+import com.alipay.sofa.koupleless.base.build.plugin.model.MavenDependencyAdapterMapping;
+import com.alipay.sofa.koupleless.base.build.plugin.model.KouplelessAdapterConfig;
+import com.alipay.sofa.koupleless.base.build.plugin.model.MavenDependencyMatcher;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.project.MavenProject;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.resolution.ArtifactRequest;
+import org.eclipse.aether.resolution.ArtifactResult;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+/**
+ * @author CodeNoobKing
+ * @date 2024/2/19
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class KouplelessBaseBuildPrePackageMojoTest {
+ @InjectMocks
+ private KouplelessBaseBuildPrePackageMojo mojo;
+
+ // create a tmp directory using os tmp
+ private File outputDirectory = null;
+
+ @Mock
+ MavenProject project;
+
+ @Mock
+ MavenSession session;
+
+ @Mock
+ RepositorySystem repositorySystem;
+
+ @Test
+ public void testLazyInitKouplelessAdapterConfig() throws Exception {
+ Dependency mockDependency = new Dependency();
+ mockDependency.setGroupId("XXX");
+ mockDependency.setArtifactId("YYY");
+ mockDependency.setVersion("ZZZ");
+
+ List commonDependencies = new ArrayList<>();
+ commonDependencies.add(mockDependency);
+
+ List mappings = new ArrayList<>();
+ mappings.add(MavenDependencyAdapterMapping.builder().adapter(mockDependency)
+ .matcher(MavenDependencyMatcher.builder().regexp(".*").build()).build());
+
+ mojo.initKouplelessAdapterConfig();
+ KouplelessAdapterConfig expected = KouplelessAdapterConfig.builder()
+ .commonDependencies(commonDependencies).adapterMappings(mappings).build();
+
+ Assert.assertEquals(expected.toString(), mojo.kouplelessAdapterConfig.toString());
+ }
+
+ @Test
+ public void testAddDependencyDynamically() throws Exception {
+ {
+ // init the adapter config
+ Dependency mockDependency = new Dependency();
+ mockDependency.setGroupId("XXX");
+ mockDependency.setArtifactId("YYY");
+ mockDependency.setVersion("ZZZ");
+
+ List commonDependencies = new ArrayList<>();
+ commonDependencies.add(mockDependency);
+
+ List mappings = new ArrayList<>();
+ mappings.add(MavenDependencyAdapterMapping.builder().adapter(mockDependency)
+ .matcher(MavenDependencyMatcher.builder().regexp(".*A:B:C.*").build()).build());
+
+ mojo.kouplelessAdapterConfig = KouplelessAdapterConfig.builder()
+ .commonDependencies(commonDependencies).adapterMappings(mappings).build();
+ }
+
+ {
+ // init maven project
+ List dependencies = new ArrayList<>();
+ Dependency mockDependency = new Dependency();
+ mockDependency.setGroupId("A");
+ mockDependency.setArtifactId("B");
+ mockDependency.setVersion("C");
+ dependencies.add(mockDependency);
+
+ doReturn(dependencies).when(project).getDependencies();
+ }
+
+ {
+ // mock the repository system
+ ArtifactResult mockArtifactResult = new ArtifactResult(new ArtifactRequest());
+ Artifact mockArtifact = mock(Artifact.class);
+ mockArtifactResult.setArtifact(mockArtifact);
+
+ URL demoJarUrl = getClass().getClassLoader().getResource("demo.jar");
+ doReturn(new File(demoJarUrl.toURI())).when(mockArtifact).getFile();
+ doReturn(mockArtifactResult).when(repositorySystem).resolveArtifact(any(), any());
+ }
+
+ {
+ // init output directory
+ mojo.outputDirectory = Files.createTempDirectory("mojotest").toFile();
+ }
+
+ mojo.execute();
+
+ {
+ Assert.assertTrue(Paths
+ .get(mojo.outputDirectory.getAbsolutePath(), "classes", "com", "example", "demo")
+ .toFile().exists());
+ }
+ }
+
+}
diff --git a/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping.yaml b/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping.yaml
new file mode 100644
index 000000000..5b6d12e83
--- /dev/null
+++ b/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping.yaml
@@ -0,0 +1,12 @@
+commonDependencies:
+ - groupId: XXX
+ artifactId: YYY
+ version: ZZZ
+
+adapterMappings:
+ - matcher:
+ regexp: ".*"
+ adapter:
+ groupId: XXX
+ artifactId: YYY
+ version: ZZZ
\ No newline at end of file
diff --git a/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/demo.jar b/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/demo.jar
new file mode 100644
index 000000000..fcb018d45
Binary files /dev/null and b/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/demo.jar differ
diff --git a/koupleless-build-plugin/pom.xml b/koupleless-build-plugin/pom.xml
new file mode 100644
index 000000000..cee193d85
--- /dev/null
+++ b/koupleless-build-plugin/pom.xml
@@ -0,0 +1,96 @@
+
+
+ 4.0.0
+
+ com.alipay.sofa.koupleless
+ koupleless-runtime
+ ${revision}
+ ../pom.xml
+
+
+ koupleless-build-plugin
+ ${revision}
+ pom
+
+
+ koupleless-base-build-plugin
+
+
+
+
+
+
+ org.apache.maven
+ maven-plugin-api
+ 3.9.0
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+ 3.8.1
+
+
+ org.apache.maven
+ maven-aether-provider
+ 3.3.9
+
+
+ org.apache.maven
+ maven-core
+ 3.8.1
+
+
+ org.apache.maven
+ maven-project
+ 2.2.1
+
+
+ com.google.guava
+ guava
+ 31.0.1-jre
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ compile
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.13.1
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.13.5
+ compile
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+ 2.13.5
+
+
+ org.apache.commons
+ commons-collections4
+ 4.4
+
+
+ junit
+ junit
+ 4.13.1
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+ 4.5.1
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 54d9bc0fc..45a5e418e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -82,6 +82,7 @@
koupleless-adapter-ext
koupleless-base-loader
koupleless-ext
+ koupleless-build-plugin