Skip to content

Commit b2f3ea4

Browse files
#1058: fixed missing JAVA_HOME env var (#1100)
1 parent 4500fc8 commit b2f3ea4

File tree

6 files changed

+83
-60
lines changed

6 files changed

+83
-60
lines changed

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Release with new features and bugfixes:
99
* https://github.com/devonfw/IDEasy/issues/1213[#1213]: Adapt log entry when tool version is not in compatible range
1010
* https://github.com/devonfw/IDEasy/issues/1272[#1272]: Add name of file with missing namespace to warning message
1111
* https://github.com/devonfw/IDEasy/issues/1190[#1190]: Add pycharm support to IDEasy
12+
* https://github.com/devonfw/IDEasy/issues/1058[#1058]: ide create still cannot handle faulty JAVA_HOME
1213

1314
The full list of changes for this release can be found in https://github.com/devonfw/IDEasy/milestone/27?closed=1[milestone 2025.05.001].
1415

cli/src/main/java/com/devonfw/tools/ide/process/ProcessContext.java

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package com.devonfw.tools.ide.process;
22

3-
import com.devonfw.tools.ide.log.IdeSubLogger;
4-
53
import java.nio.file.Path;
64
import java.util.List;
75
import java.util.Objects;
86

7+
import com.devonfw.tools.ide.log.IdeSubLogger;
8+
99
/**
1010
* Wrapper for {@link ProcessBuilder} to simplify its usage and avoid common mistakes and pitfalls.
1111
*/
@@ -26,8 +26,9 @@ public interface ProcessContext extends EnvironmentContext {
2626
/**
2727
* Sets the executable command to be {@link #run()}.
2828
*
29-
* @param executable the {@link Path} to the command to be executed by {@link #run()}. Depending on your operating system and the extension of the executable
30-
* or OS specific conventions. So e.g. a *.cmd or *.bat file will be called via CMD shell on windows while a *.sh file will be called via Bash, etc.
29+
* @param executable the {@link Path} to the command to be executed by {@link #run()}. Depending on your operating system and the extension of the
30+
* executable or OS specific conventions. So e.g. a *.cmd or *.bat file will be called via CMD shell on windows while a *.sh file will be called via Bash,
31+
* etc.
3132
* @return this {@link ProcessContext} for fluent API calls.
3233
*/
3334
ProcessContext executable(Path executable);
@@ -165,41 +166,12 @@ default String runAndGetSingleOutput(String executable, String... arguments) {
165166
*/
166167
default String runAndGetSingleOutput(IdeSubLogger logger, String executable, String... arguments) {
167168

168-
String errorMessage;
169169
executable(executable).addArgs(arguments);
170170
if (logger == null) {
171171
errorHandling(ProcessErrorHandling.THROW_ERR);
172172
}
173173
ProcessResult result = run(ProcessMode.DEFAULT_CAPTURE);
174-
if (result.isSuccessful()) {
175-
List<String> out = result.getOut();
176-
int size = out.size();
177-
if (size == 1) {
178-
return out.get(0);
179-
} else if (size == 0) {
180-
errorMessage = "No output received from " + result.getCommand();
181-
} else {
182-
StringBuilder sb = new StringBuilder();
183-
sb.append("Expected single line of output but received ");
184-
sb.append(size);
185-
sb.append(" lines from ");
186-
sb.append(result.getCommand());
187-
sb.append(":");
188-
for (String line : out) {
189-
sb.append("\n");
190-
sb.append(line);
191-
}
192-
errorMessage = sb.toString();
193-
}
194-
} else {
195-
errorMessage = "Command " + result.getCommand() + " failed with exit code " + result.getExitCode();
196-
}
197-
if (logger == null) {
198-
throw new IllegalStateException(errorMessage);
199-
} else {
200-
logger.log(errorMessage);
201-
return null;
202-
}
174+
return result.getSingleOutput(logger);
203175
}
204176

205177
/**

cli/src/main/java/com/devonfw/tools/ide/process/ProcessResult.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.devonfw.tools.ide.cli.CliProcessException;
66
import com.devonfw.tools.ide.context.IdeContext;
77
import com.devonfw.tools.ide.log.IdeLogLevel;
8+
import com.devonfw.tools.ide.log.IdeSubLogger;
89

910
/**
1011
* Result of a {@link Process} execution.
@@ -66,6 +67,13 @@ default boolean isSuccessful() {
6667
return getExitCode() == SUCCESS;
6768
}
6869

70+
/**
71+
* @param logger the {@link IdeSubLogger logger} to use.
72+
* @return the first captured standard out. Will be {@code null} if not captured but redirected.
73+
* @throws IllegalStateException if more than one output was captured and the {@link IdeSubLogger logger} was null.
74+
*/
75+
String getSingleOutput(IdeSubLogger logger) throws IllegalStateException;
76+
6977
/**
7078
* @return the {@link List} with the lines captured on standard out. Will be {@code null} if not captured but redirected.
7179
*/

cli/src/main/java/com/devonfw/tools/ide/process/ProcessResultImpl.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.devonfw.tools.ide.cli.CliProcessException;
88
import com.devonfw.tools.ide.context.IdeContext;
99
import com.devonfw.tools.ide.log.IdeLogLevel;
10+
import com.devonfw.tools.ide.log.IdeSubLogger;
1011

1112
/**
1213
* Implementation of {@link ProcessResult}.
@@ -56,6 +57,40 @@ public int getExitCode() {
5657
return this.exitCode;
5758
}
5859

60+
@Override
61+
public String getSingleOutput(IdeSubLogger logger) throws IllegalStateException {
62+
String errorMessage;
63+
if (this.isSuccessful()) {
64+
List<String> out = this.getOut();
65+
int size = out.size();
66+
if (size == 1) {
67+
return out.getFirst();
68+
} else if (size == 0) {
69+
errorMessage = "No output received from " + this.getCommand();
70+
} else {
71+
StringBuilder sb = new StringBuilder();
72+
sb.append("Expected single line of output but received ");
73+
sb.append(size);
74+
sb.append(" lines from ");
75+
sb.append(this.getCommand());
76+
sb.append(":");
77+
for (String line : out) {
78+
sb.append("\n");
79+
sb.append(line);
80+
}
81+
errorMessage = sb.toString();
82+
}
83+
} else {
84+
errorMessage = "Command " + this.getCommand() + " failed with exit code " + this.getExitCode();
85+
}
86+
if (logger == null) {
87+
throw new IllegalStateException(errorMessage);
88+
} else {
89+
logger.log(errorMessage);
90+
return null;
91+
}
92+
}
93+
5994
@Override
6095
public List<String> getOut() {
6196

cli/src/main/java/com/devonfw/tools/ide/tool/mvn/Mvn.java

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.devonfw.tools.ide.context.IdeContext;
1414
import com.devonfw.tools.ide.git.GitContext;
1515
import com.devonfw.tools.ide.process.ProcessContext;
16+
import com.devonfw.tools.ide.process.ProcessErrorHandling;
1617
import com.devonfw.tools.ide.process.ProcessMode;
1718
import com.devonfw.tools.ide.process.ProcessResult;
1819
import com.devonfw.tools.ide.step.Step;
@@ -96,12 +97,7 @@ private void createSettingsSecurityFile(Path settingsSecurityFile) {
9697
secureRandom.nextBytes(randomBytes);
9798
String base64String = Base64.getEncoder().encodeToString(randomBytes);
9899

99-
ProcessContext pc = this.context.newProcess().executable("mvn");
100-
pc.addArgs("--encrypt-master-password", base64String);
101-
102-
ProcessResult result = pc.run(ProcessMode.DEFAULT_CAPTURE);
103-
104-
String encryptedMasterPassword = result.getOut().get(0);
100+
String encryptedMasterPassword = retrievePassword("--encrypt-master-password", base64String);
105101

106102
String settingsSecurityXml =
107103
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<settingsSecurity>\n" + " <master>" + encryptedMasterPassword + "</master>\n"
@@ -154,17 +150,20 @@ private String getEncryptedPassword(String variable) {
154150

155151
String input = this.context.askForInput("Please enter secret value for variable " + variable + ":");
156152

157-
ProcessContext pc = this.context.newProcess().executable("mvn");
158-
pc.addArgs("--encrypt-password", input);
159-
pc.addArg(getSettingsSecurityProperty());
160-
ProcessResult result = pc.run(ProcessMode.DEFAULT_CAPTURE);
161-
162-
String encryptedPassword = result.getOut().get(0);
153+
String encryptedPassword = retrievePassword("--encrypt-password", input);
163154
this.context.info("Encrypted as " + encryptedPassword);
164155

165156
return encryptedPassword;
166157
}
167158

159+
private String retrievePassword(String args, String input) {
160+
161+
ProcessResult result = runTool(ProcessMode.DEFAULT_CAPTURE, ProcessErrorHandling.LOG_WARNING, this.context.newProcess(), args, input,
162+
getSettingsSecurityProperty());
163+
164+
return result.getSingleOutput(null);
165+
}
166+
168167
private Set<String> findVariables(String content) {
169168

170169
Set<String> variables = new LinkedHashSet<>();
@@ -250,11 +249,24 @@ public Path getMavenConfFolder(boolean legacy) {
250249
public String getMavenArgs() {
251250
Path mavenConfFolder = getMavenConfFolder(false);
252251
Path mvnSettingsFile = mavenConfFolder.resolve(Mvn.SETTINGS_FILE);
253-
if (!Files.exists(mvnSettingsFile)) {
252+
Path settingsSecurityFile = mavenConfFolder.resolve(SETTINGS_SECURITY_FILE);
253+
boolean settingsFileExists = Files.exists(mvnSettingsFile);
254+
boolean securityFileExists = Files.exists(settingsSecurityFile);
255+
if (!settingsFileExists && !securityFileExists) {
254256
return null;
255257
}
256-
String settingsPath = mvnSettingsFile.toString();
257-
return "-s " + settingsPath + " " + getSettingsSecurityProperty();
258+
StringBuilder sb = new StringBuilder();
259+
if (settingsFileExists) {
260+
sb.append("-s ");
261+
sb.append(mvnSettingsFile);
262+
}
263+
if (securityFileExists) {
264+
if (!sb.isEmpty()) {
265+
sb.append(" ");
266+
}
267+
sb.append(getSettingsSecurityProperty());
268+
}
269+
return sb.toString();
258270
}
259271

260272
private String getSettingsSecurityProperty() {

cli/src/test/java/com/devonfw/tools/ide/tool/mvn/MvnTest.java

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
import org.junit.jupiter.api.Test;
1212

13-
import com.devonfw.tools.ide.commandlet.InstallCommandlet;
1413
import com.devonfw.tools.ide.context.AbstractIdeContextTest;
1514
import com.devonfw.tools.ide.context.IdeTestContext;
1615
import com.devonfw.tools.ide.variable.IdeVariables;
@@ -22,7 +21,6 @@ public class MvnTest extends AbstractIdeContextTest {
2221

2322
private static final String PROJECT_MVN = "mvn";
2423

25-
//private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\$\\[(.*?)\\]");
2624
private static final Pattern VARIABLE_PATTERN = Pattern.compile("<([^>]+)>(.*?)</\\1>");
2725

2826
/**
@@ -36,11 +34,10 @@ public void testMvnInstall() throws IOException {
3634
// arrange
3735
IdeTestContext context = newContext(PROJECT_MVN);
3836
context.setAnswers("testLogin", "testPassword");
39-
InstallCommandlet install = context.getCommandletManager().getCommandlet(InstallCommandlet.class);
40-
install.tool.setValueAsString("mvn", context);
37+
Mvn mvn = context.getCommandletManager().getCommandlet(Mvn.class);
4138

4239
// act
43-
install.run();
40+
mvn.run();
4441

4542
// assert
4643
checkInstallation(context);
@@ -56,14 +53,12 @@ public void testMvnRun() throws IOException {
5653
// arrange
5754
IdeTestContext context = newContext(PROJECT_MVN);
5855
context.setAnswers("testLogin", "testPassword");
59-
InstallCommandlet install = context.getCommandletManager().getCommandlet(InstallCommandlet.class);
60-
install.tool.setValueAsString("mvn", context);
61-
Mvn commandlet = (Mvn) install.tool.getValue();
62-
commandlet.arguments.addValue("foo");
63-
commandlet.arguments.addValue("bar");
56+
Mvn mvn = context.getCommandletManager().getCommandlet(Mvn.class);
57+
mvn.arguments.addValue("foo");
58+
mvn.arguments.addValue("bar");
6459

6560
// act
66-
commandlet.run();
61+
mvn.run();
6762

6863
// assert
6964
assertThat(context).logAtInfo().hasMessage("mvn " + "foo bar");

0 commit comments

Comments
 (0)