diff --git a/README.md b/README.md
index 21300cd5..4bae3ad2 100644
--- a/README.md
+++ b/README.md
@@ -328,6 +328,9 @@ System.setProperty("EXHORT_PYTHON_PATH", "/path/to/python");
System.setProperty("EXHORT_PIP_PATH", "/path/to/pip");
// Configure proxy for all requests
System.setProperty("EXHORT_PROXY_URL", "http://proxy.example.com:8080");
+// Configure Maven settings and repository
+System.setProperty("EXHORT_MVN_USER_SETTINGS", "/path/to/custom/settings.xml");
+System.setProperty("EXHORT_MVN_LOCAL_REPO", "/path/to/custom/local/repository");
```
> Environment variables takes precedence.
@@ -436,6 +439,47 @@ following keys for setting custom paths for the said executables.
+#### Maven Configuration
+
+You can customize Maven behavior by setting additional environment variables or Java properties:
+
+
+
+| Configuration |
+Environment Variable |
+Description |
+Default |
+
+
+| Maven User Settings |
+EXHORT_MVN_USER_SETTINGS |
+Path to custom Maven settings.xml file |
+Uses Maven's default settings |
+
+
+| Maven Local Repository |
+EXHORT_MVN_LOCAL_REPO |
+Path to custom Maven local repository directory |
+Uses Maven's default local repository |
+
+
+
+**Examples:**
+
+Using environment variables:
+```bash
+export EXHORT_MVN_USER_SETTINGS=/home/user/.m2/custom-settings.xml
+export EXHORT_MVN_LOCAL_REPO=/home/user/custom-maven-repo
+```
+
+Using Java properties:
+```java
+System.setProperty("EXHORT_MVN_USER_SETTINGS", "/home/user/.m2/custom-settings.xml");
+System.setProperty("EXHORT_MVN_LOCAL_REPO", "/home/user/custom-maven-repo");
+```
+
+> Environment variables take precedence over Java properties.
+
#### Match Manifest Versions Feature
##### Background
diff --git a/src/main/java/com/redhat/exhort/providers/JavaMavenProvider.java b/src/main/java/com/redhat/exhort/providers/JavaMavenProvider.java
index d7c006c5..7de45fe7 100644
--- a/src/main/java/com/redhat/exhort/providers/JavaMavenProvider.java
+++ b/src/main/java/com/redhat/exhort/providers/JavaMavenProvider.java
@@ -65,28 +65,23 @@ public JavaMavenProvider(Path manifest) {
@Override
public Content provideStack() throws IOException {
- var mvnCleanCmd =
- new String[] {mvnExecutable, "clean", "-f", manifest.toString(), "--batch-mode", "-q"};
+ var mvnCleanCmd = buildMvnCommandArgs("clean", "-f", manifest.toString(), "--batch-mode", "-q");
var mvnEnvs = getMvnExecEnvs();
// execute the clean command
- Operations.runProcess(manifest.getParent(), mvnCleanCmd, mvnEnvs);
+ Operations.runProcess(manifest.getParent(), mvnCleanCmd.toArray(String[]::new), mvnEnvs);
// create a temp file for storing the dependency tree in
var tmpFile = Files.createTempFile("exhort_dot_graph_", null);
// the tree command will build the project and create the dependency tree in the temp file
var mvnTreeCmd =
- new ArrayList() {
- {
- add(mvnExecutable);
- add("org.apache.maven.plugins:maven-dependency-plugin:3.6.0:tree");
- add("-Dverbose");
- add("-DoutputType=text");
- add(String.format("-DoutputFile=%s", tmpFile.toString()));
- add("-f");
- add(manifest.toString());
- add("--batch-mode");
- add("-q");
- }
- };
+ buildMvnCommandArgs(
+ "org.apache.maven.plugins:maven-dependency-plugin:3.6.0:tree",
+ "-Dverbose",
+ "-DoutputType=text",
+ String.format("-DoutputFile=%s", tmpFile.toString()),
+ "-f",
+ manifest.toString(),
+ "--batch-mode",
+ "-q");
// if we have dependencies marked as ignored, exclude them from the tree command
var ignored =
getDependencies(manifest).stream()
@@ -133,18 +128,17 @@ public Content provideComponent() throws IOException {
private Content generateSbomFromEffectivePom() throws IOException {
var tmpEffPom = Files.createTempFile("exhort_eff_pom_", ".xml");
var mvnEffPomCmd =
- new String[] {
- mvnExecutable,
- "clean",
- "help:effective-pom",
- String.format("-Doutput=%s", tmpEffPom.toString()),
- "-f",
- manifest.toString(),
- "--batch-mode",
- "-q"
- };
+ buildMvnCommandArgs(
+ "clean",
+ "help:effective-pom",
+ String.format("-Doutput=%s", tmpEffPom.toString()),
+ "-f",
+ manifest.toString(),
+ "--batch-mode",
+ "-q");
// execute the effective pom command
- Operations.runProcess(manifest.getParent(), mvnEffPomCmd, getMvnExecEnvs());
+ Operations.runProcess(
+ manifest.getParent(), mvnEffPomCmd.toArray(String[]::new), getMvnExecEnvs());
if (debugLoggingIsNeeded()) {
String CaEffectivePoM = Files.readString(tmpEffPom);
log.info(
@@ -345,6 +339,28 @@ Map getMvnExecEnvs() {
return null;
}
+ private List buildMvnCommandArgs(String... baseArgs) {
+ List args = new ArrayList<>();
+ args.add(mvnExecutable);
+
+ var userSettingsFile = Operations.getMavenConfig("USER_SETTINGS");
+ if (userSettingsFile != null) {
+ args.add("-s");
+ args.add(userSettingsFile);
+ }
+
+ var localRepository = Operations.getMavenConfig("LOCAL_REPO");
+ if (localRepository != null) {
+ args.add("-Dmaven.repo.local=" + localRepository);
+ }
+
+ for (String arg : baseArgs) {
+ args.add(arg);
+ }
+
+ return args;
+ }
+
// NOTE if we want to include "scope" tags in ignore,
// add property here and a case in the start-element-switch in the getIgnored method
diff --git a/src/main/java/com/redhat/exhort/tools/Operations.java b/src/main/java/com/redhat/exhort/tools/Operations.java
index 21327f0d..8b3f9a10 100644
--- a/src/main/java/com/redhat/exhort/tools/Operations.java
+++ b/src/main/java/com/redhat/exhort/tools/Operations.java
@@ -316,6 +316,17 @@ public static boolean getWrapperPreference(String name) {
return Environment.get("EXHORT_PREFER_" + name.toUpperCase() + "W") != null;
}
+ /**
+ * Retrieves a Maven configuration value from an environment variable.
+ *
+ * @param configName the configuration name (e.g., "USER_SETTINGS", "LOCAL_REPO")
+ * @return the configuration value if set and not blank, null otherwise
+ */
+ public static String getMavenConfig(String configName) {
+ String configValue = Environment.get("EXHORT_MVN_" + configName);
+ return (configValue != null && !configValue.isBlank()) ? configValue : null;
+ }
+
/**
* Attempts to retrieve the root directory of a Git repository for the given working directory.
*