This is an automated email from the ASF dual-hosted git repository.
mbien pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push:
new 0ab330adb9 [NETBEANS-5479] improve maven multithreaded execution
detection.
new 27ed405fe6 Merge pull request #5482 from asbachb/bugfix/5479
0ab330adb9 is described below
commit 0ab330adb9d07c7646354e4ea450ad4f41f1ea5f
Author: Benjamin Asbach <[email protected]>
AuthorDate: Sat Feb 18 13:20:13 2023 +0100
[NETBEANS-5479] improve maven multithreaded execution detection.
mvn is ST by default, mvnd is MT by default. Lets try to detect the
execution mode a bit better by inspecting the command line parameters.
MT modes can't use the event spy.
contains minor performance improvement:
try to get maven version by analyzing `maven-core.jar` file name.
this is a lot faster than opening the jar, parsing and evaluating the
properties file. Since the file name approach does not work for
maven 2 the previous logic was kept.
Co-authored-by: Michael Bien <[email protected]>
---
.../maven/execute/MavenCommandLineExecutor.java | 53 ++++++-
.../maven/execute/cmd/ShellConstructor.java | 4 +-
.../modules/maven/options/MavenSettings.java | 26 +++-
.../MavenCommandParametersAnalyzerTest.java | 132 ++++++++++++++++
.../MavenDaemonCommandParametersAnalyzerTest.java | 169 +++++++++++++++++++++
5 files changed, 373 insertions(+), 11 deletions(-)
diff --git
a/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java
b/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java
index 286b478664..99e500c34c 100644
---
a/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java
+++
b/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java
@@ -28,6 +28,7 @@ import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -149,6 +150,7 @@ public class MavenCommandLineExecutor extends
AbstractMavenExecutor {
private static final RequestProcessor UPDATE_INDEX_RP = new
RequestProcessor(RunUtils.class.getName(), 5);
private static final String ICON_MAVEN_PROJECT =
"org/netbeans/modules/maven/resources/Maven2Icon.gif"; // NOI18N
+
/**
* Execute maven build in NetBeans execution engine.
* Most callers should rather use {@link #run} as this variant does no
(non-late-bound) prerequisite checks.
@@ -855,6 +857,11 @@ public class MavenCommandLineExecutor extends
AbstractMavenExecutor {
return version != null && version.startsWith("2");
}
+ private boolean isMavenDaemon() {
+ File mvnHome = EmbedderFactory.getEffectiveMavenHome();
+ return MavenSettings.isMavenDaemon(Paths.get(mvnHome.getPath()));
+ }
+
private void injectEventSpy(final BeanRunConfig clonedConfig) {
//TEMP
String mavenPath =
clonedConfig.getProperties().get(CosChecker.MAVENEXTCLASSPATH);
@@ -878,16 +885,48 @@ public class MavenCommandLineExecutor extends
AbstractMavenExecutor {
}
private boolean isMultiThreaded(BeanRunConfig clonedConfig) {
- String list = MavenSettings.getDefault().getDefaultOptions();
- for (String s : clonedConfig.getGoals()) {
- list = list + " " + s;
- }
+
+ List<String> params = new ArrayList<>();
+
params.addAll(Arrays.asList(MavenSettings.getDefault().getDefaultOptions().split("
")));
+ params.addAll(clonedConfig.getGoals());
if (clonedConfig.getPreExecution() != null) {
- for (String s : clonedConfig.getPreExecution().getGoals()) {
- list = list + " " + s;
+ params.addAll(clonedConfig.getPreExecution().getGoals());
+ }
+
+ return isMavenDaemon() ? isMultiThreadedMvnd(params)
+ : isMultiThreadedMaven(params);
+ }
+
+ // mvnd is MT by default
+ static boolean isMultiThreadedMvnd(List<String> params) {
+ for (int i = 0; i < params.size(); i++) {
+ String p = params.get(i);
+ if (p.equals("-1") || p.equals("--serial") ||
p.equals("-Dmvnd.serial")) { // "behave like standard maven" mode
+ return false;
+ }
+ if (i + 1 < params.size() && (p.equals("-T") ||
p.equals("--threads"))) {
+ if (params.get(i+1).equals("1")) {
+ return false;
+ }
+ }
+ try {
+ if (p.startsWith("-Dmvnd.threads=") &&
Integer.parseInt(p.substring(15)) == 1) {
+ return false;
+ }
+ } catch (NumberFormatException ignored) {}
+ }
+ return true;
+ }
+
+ // mvn is ST by default
+ static boolean isMultiThreadedMaven(List<String> params) {
+ for (int i = 0; i < params.size() - 1; i++) {
+ String p = params.get(i);
+ if ((p.equals("-T") || p.equals("--threads")) &&
!params.get(i+1).equals("1")) {
+ return true;
}
}
- return list.contains("-T") || list.contains("--threads");
+ return false;
}
private File guessBestMaven(RunConfig clonedConfig, InputOutput ioput) {
diff --git
a/java/maven/src/org/netbeans/modules/maven/execute/cmd/ShellConstructor.java
b/java/maven/src/org/netbeans/modules/maven/execute/cmd/ShellConstructor.java
index d1d661585f..5433e7f413 100644
---
a/java/maven/src/org/netbeans/modules/maven/execute/cmd/ShellConstructor.java
+++
b/java/maven/src/org/netbeans/modules/maven/execute/cmd/ShellConstructor.java
@@ -20,7 +20,6 @@
package org.netbeans.modules.maven.execute.cmd;
import java.io.File;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -44,8 +43,7 @@ public class ShellConstructor implements Constructor {
public List<String> construct() {
// use mvnd if its the home of a daemon
- String mavenDaemonSuffixDetection = Utilities.isWindows() ? ".exe" :
"";
- String ex = Files.exists(Paths.get(mavenHome.getPath(), "bin", "mvnd"
+ mavenDaemonSuffixDetection)) ? "mvnd" : "mvn"; //NOI18N
+ String ex =
MavenSettings.isMavenDaemon(Paths.get(mavenHome.getPath())) ? "mvnd" : "mvn";
//NOI18N
List<String> command = new ArrayList<>();
diff --git
a/java/maven/src/org/netbeans/modules/maven/options/MavenSettings.java
b/java/maven/src/org/netbeans/modules/maven/options/MavenSettings.java
index bda5cbabf2..850fd76708 100644
--- a/java/maven/src/org/netbeans/modules/maven/options/MavenSettings.java
+++ b/java/maven/src/org/netbeans/modules/maven/options/MavenSettings.java
@@ -31,12 +31,14 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.maven.execution.MavenExecutionRequest;
@@ -48,6 +50,7 @@ import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.util.NbBundle;
import org.openide.util.NbPreferences;
+import org.openide.util.Utilities;
import org.openide.util.WeakSet;
/**
@@ -87,6 +90,8 @@ public final class MavenSettings {
private static final String PROP_USE_REGISTRY = "usePluginRegistry";
//NOI18N
public static final String PROP_NETWORK_PROXY = "networkProxy";
+ private static final Pattern MAVEN_CORE_JAR_PATTERN =
Pattern.compile("maven-core-(\\d+\\.\\d+\\.\\d+)\\.jar"); // NOI18N
+
private static final MavenSettings INSTANCE = new MavenSettings();
private final Set<PropertyChangeListener> listeners = new WeakSet<>();
@@ -471,7 +476,6 @@ public final class MavenSettings {
}
public static @CheckForNull String getCommandLineMavenVersion(File
mavenHome) {
-
Path lib = Paths.get(mavenHome.getPath(), "lib"); // mvn layout
// NOI18N
if (!Files.exists(lib)) {
lib = Paths.get(mavenHome.getPath(), "mvn", "lib"); // mvnd
layout // NOI18N
@@ -480,6 +484,20 @@ public final class MavenSettings {
}
}
+ // try to resolve maven version by checking maven-core jar name
+ try (Stream<String> mavenCoreVersions = Files.list(lib)
+ .map(file -> file.getFileName().toString())
+ .filter(file -> file.startsWith("maven-core")) // NOI18N
+ .map(file -> MAVEN_CORE_JAR_PATTERN.matcher(file))
+ .filter(matcher -> matcher.matches())
+ .map(matcher -> matcher.group(1))) {
+ Optional<String> mavenCoreVersion = mavenCoreVersions.findFirst();
+ if (mavenCoreVersion.isPresent()) {
+ return mavenCoreVersion.get();
+ }
+ } catch (IOException ignored) {}
+
+ // try to resolve maven version by parsing pom.properties
try {
try (Stream<Path> jars = Files.list(lib).filter(file ->
file.toString().endsWith(".jar"))) { // NOI18N
for (Path jar : jars.collect(Collectors.toList())) {
@@ -500,6 +518,12 @@ public final class MavenSettings {
return null;
}
+ public static boolean isMavenDaemon(Path mavenHome) {
+ String mvndExecutableName = Utilities.isWindows() ? "mvnd.exe" :
"mvnd";
+
+ return
Files.exists(mavenHome.resolve("bin").resolve(mvndExecutableName));
+ }
+
private static List<String> searchMavenRuntimes(String[] paths, boolean
stopOnFirstValid) {
List<String> runtimes = new ArrayList<>();
for (String path : paths) {
diff --git
a/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MavenCommandParametersAnalyzerTest.java
b/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MavenCommandParametersAnalyzerTest.java
new file mode 100644
index 0000000000..e7f7ef4947
--- /dev/null
+++
b/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MavenCommandParametersAnalyzerTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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 org.netbeans.modules.maven.execute;
+
+import java.util.Arrays;
+
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+
+import org.junit.Test;
+
+/**
+ *
+ * @author Benjamin Asbach ([email protected])
+ */
+public class MavenCommandParametersAnalyzerTest {
+
+ @Test
+ public void defaultIsSingleThreaded() {
+ assertFalse(isMultiThreadedMaven(""));
+ }
+
+ @Test
+ public void validateMultiThreaded1() {
+ assertTrue(isMultiThreadedMaven("-T 10"));
+ }
+
+ @Test
+ public void validateMultiThreaded2() {
+ assertTrue(isMultiThreadedMaven("-T 2"));
+ }
+
+ @Test
+ public void validateMultiThreaded3() {
+ assertTrue(isMultiThreadedMaven("-Dmaven.test.skip=true -T 10"));
+ }
+
+ @Test
+ public void validateMultiThreaded4() {
+ assertTrue(isMultiThreadedMaven("-Dmaven.test.skip=true -T 2"));
+ }
+
+ @Test
+ public void validateMultiThreaded5() {
+ assertTrue(isMultiThreadedMaven("-Dmaven.test.skip=true -T 10
-Dmaven.test.skip=true "));
+ }
+
+ @Test
+ public void validateMultiThreaded6() {
+ assertTrue(isMultiThreadedMaven("-Dmaven.test.skip=true -T 2
-Dmaven.test.skip=true "));
+ }
+
+ @Test
+ public void validateMultiThreaded7() {
+ assertTrue(isMultiThreadedMaven("-T 10 -Dmaven.test.skip=true"));
+ }
+
+ @Test
+ public void validateMultiThreaded8() {
+ assertTrue(isMultiThreadedMaven("-T 2 -Dmaven.test.skip=true"));
+ }
+
+ @Test
+ public void validateMultiThreaded9() {
+ assertTrue(isMultiThreadedMaven("--threads 10"));
+ }
+
+ @Test
+ public void validateMultiThreaded10() {
+ assertTrue(isMultiThreadedMaven("--threads 2"));
+ }
+
+ @Test
+ public void validateMultiThreaded11() {
+ assertTrue(isMultiThreadedMaven("-Dmaven.test.skip=true --threads
10"));
+ }
+
+ @Test
+ public void validateMultiThreaded12() {
+ assertTrue(isMultiThreadedMaven("-Dmaven.test.skip=true --threads 2"));
+ }
+
+ @Test
+ public void validateMultiThreaded13() {
+ assertTrue(isMultiThreadedMaven("-Dmaven.test.skip=true --threads 10
-Dmaven.test.skip=true "));
+ }
+
+ @Test
+ public void validateMultiThreaded14() {
+ assertTrue(isMultiThreadedMaven("-Dmaven.test.skip=true --threads 2
-Dmaven.test.skip=true "));
+ }
+
+ @Test
+ public void validateMultiThreaded15() {
+ assertTrue(isMultiThreadedMaven("--threads 10
-Dmaven.test.skip=true"));
+ }
+
+ @Test
+ public void validateMultiThreaded16() {
+ assertTrue(isMultiThreadedMaven("--threads 2 -Dmaven.test.skip=true"));
+ }
+
+ @Test
+ public void validateSingleThreaded1() {
+ assertFalse(isMultiThreadedMaven("--threads 1"));
+ }
+
+ @Test
+ public void validateSingleThreaded2() {
+ assertFalse(isMultiThreadedMaven("-T 1"));
+ }
+
+ private boolean isMultiThreadedMaven(String params) {
+ return
MavenCommandLineExecutor.isMultiThreadedMaven(Arrays.asList(params.split(" ")));
+ }
+}
diff --git
a/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MavenDaemonCommandParametersAnalyzerTest.java
b/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MavenDaemonCommandParametersAnalyzerTest.java
new file mode 100644
index 0000000000..edeeb9c933
--- /dev/null
+++
b/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MavenDaemonCommandParametersAnalyzerTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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 org.netbeans.modules.maven.execute;
+
+import java.util.Arrays;
+
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+
+import org.junit.Test;
+
+/**
+ *
+ * @author Benjamin Asbach ([email protected])
+ */
+public class MavenDaemonCommandParametersAnalyzerTest {
+
+ @Test
+ public void defaultIsSingleThreaded() {
+ assertTrue(checkisMultiThreadedMvnd(""));
+ }
+
+ @Test
+ public void validateMultiThreaded1() {
+ assertTrue(checkisMultiThreadedMvnd("-T 10"));
+ }
+
+ @Test
+ public void validateMultiThreaded3() {
+ assertTrue(checkisMultiThreadedMvnd("-Dmaven.test.skip=true -T 10"));
+ }
+
+ @Test
+ public void validateMultiThreaded5() {
+ assertTrue(checkisMultiThreadedMvnd("-Dmaven.test.skip=true -T 10
-Dmaven.test.skip=true "));
+ }
+
+ @Test
+ public void validateMultiThreaded7() {
+ assertTrue(checkisMultiThreadedMvnd("-T 10 -Dmaven.test.skip=true"));
+ }
+
+
+ @Test
+ public void validateMultiThreaded2() {
+ assertTrue(checkisMultiThreadedMvnd("-T 2"));
+ }
+
+ @Test
+ public void validateMultiThreaded4() {
+ assertTrue(checkisMultiThreadedMvnd("-Dmaven.test.skip=true -T 2"));
+ }
+
+ @Test
+ public void validateMultiThreaded6() {
+ assertTrue(checkisMultiThreadedMvnd("-Dmaven.test.skip=true -T 2
-Dmaven.test.skip=true "));
+ }
+
+ @Test
+ public void validateMultiThreaded8() {
+ assertTrue(checkisMultiThreadedMvnd("-T 2 -Dmaven.test.skip=true"));
+ }
+
+
+ @Test
+ public void validateMultiThreaded9() {
+ assertTrue(checkisMultiThreadedMvnd("--threads 10"));
+ }
+
+ @Test
+ public void validateMultiThreaded11() {
+ assertTrue(checkisMultiThreadedMvnd("-Dmaven.test.skip=true --threads
10"));
+ }
+
+ @Test
+ public void validateMultiThreaded13() {
+ assertTrue(checkisMultiThreadedMvnd("-Dmaven.test.skip=true --threads
10 -Dmaven.test.skip=true "));
+ }
+
+ @Test
+ public void validateMultiThreaded15() {
+ assertTrue(checkisMultiThreadedMvnd("--threads 10
-Dmaven.test.skip=true"));
+ }
+
+ @Test
+ public void validateMultiThreaded10() {
+ assertTrue(checkisMultiThreadedMvnd("--threads 2"));
+ }
+
+ @Test
+ public void validateMultiThreaded12() {
+ assertTrue(checkisMultiThreadedMvnd("-Dmaven.test.skip=true --threads
2"));
+ }
+
+ @Test
+ public void validateMultiThreaded14() {
+ assertTrue(checkisMultiThreadedMvnd("-Dmaven.test.skip=true --threads
2 -Dmaven.test.skip=true "));
+ }
+
+ @Test
+ public void validateMultiThreaded16() {
+ assertTrue(checkisMultiThreadedMvnd("--threads 2
-Dmaven.test.skip=true"));
+ }
+
+ @Test
+ public void validateMultiThreaded17() {
+ assertTrue(checkisMultiThreadedMvnd("-Dmvnd.threads=2
-Dmaven.test.skip=true"));
+ }
+
+ @Test
+ public void validateSingleThreaded1() {
+ assertFalse(checkisMultiThreadedMvnd("--threads 1"));
+ }
+
+ @Test
+ public void validateSingleThreaded3() {
+ assertFalse(checkisMultiThreadedMvnd("-Dmaven.test.skip=true --threads
1"));
+ }
+
+ @Test
+ public void validateSingleThreaded5() {
+ assertFalse(checkisMultiThreadedMvnd("--threads 1
-Dmaven.test.skip=true"));
+ }
+
+ @Test
+ public void validateSingleThreaded2() {
+ assertFalse(checkisMultiThreadedMvnd("-T 1"));
+ }
+
+ @Test
+ public void validateSingleThreaded4() {
+ assertFalse(checkisMultiThreadedMvnd("-Dmaven.test.skip=true -T 1"));
+ }
+
+ @Test
+ public void validateSingleThreaded6() {
+ assertFalse(checkisMultiThreadedMvnd("-T 1 -Dmaven.test.skip=true"));
+ }
+
+ @Test
+ public void validateSingleThreaded7() {
+ assertFalse(checkisMultiThreadedMvnd("-Dmvnd.threads=1"));
+ }
+
+ @Test
+ public void validateSingleThreaded8() {
+ assertTrue(checkisMultiThreadedMvnd("-Dmvnd.threads=foo
-Dmaven.test.skip=true"));
+ }
+
+ private boolean checkisMultiThreadedMvnd(String params) {
+ return
MavenCommandLineExecutor.isMultiThreadedMvnd(Arrays.asList(params.split(" ")));
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists