getJavaOptions() {
+ return javaOpts.asList();
+ }
+
+ /**
+ * Adds an option which will be passed to JBoss Modules.
+ *
+ * Note that {@code -mp} or {@code --modulepath} is not supported. Use {@link #addModuleDir(String)} to add a module
+ * directory.
+ *
+ *
+ * @param arg the argument to add
+ *
+ * @return the builder
+ */
+ public JBossModulesCommandBuilder addModuleOption(final String arg) {
+ if (arg != null) {
+ if (arg.startsWith("-javaagent:")) {
+ addModuleAgent = true;
+ } else if ("-mp".equals(arg) || "--modulepath".equals(arg)) {
+ throw MESSAGES.invalidArgument(arg, "addModuleOption");
+ } else if ("-secmgr".equals(arg)) {
+ throw MESSAGES.invalidArgument(arg, "setUseSecurityManager");
+ }
+ moduleOpts.add(arg);
+ }
+ return this;
+ }
+
+ /**
+ * Adds the options which will be passed to JBoss Modules.
+ *
+ * Note that {@code -mp} or {@code --modulepath} is not supported. Use {@link #addModuleDirs(String...)} to add a
+ * module directory.
+ *
+ *
+ * @param args the argument to add
+ *
+ * @return the builder
+ */
+ public JBossModulesCommandBuilder addModuleOptions(final String... args) {
+ if (args != null) {
+ for (String arg : args) {
+ addModuleOption(arg);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Adds the options which will be passed to JBoss Modules.
+ *
+ * Note that {@code -mp} or {@code --modulepath} is not supported. Use {@link #addModuleDirs(Iterable)} to add a
+ * module directory.
+ *
+ *
+ * @param args the argument to add
+ *
+ * @return the builder
+ */
+ public JBossModulesCommandBuilder addModuleOptions(final Iterable args) {
+ if (args != null) {
+ for (String arg : args) {
+ addModuleOption(arg);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Clears the current module options and adds the options which will be passed to JBoss Modules.
+ *
+ * Note that {@code -mp} or {@code --modulepath} is not supported. Use {@link #addModuleDirs(String...)} to add a
+ * module directory.
+ *
+ *
+ * @param args the argument to use
+ *
+ * @return the builder
+ */
+ public JBossModulesCommandBuilder setModuleOptions(final String... args) {
+ moduleOpts.clear();
+ addModuleOptions(args);
+ return this;
+ }
+
+ /**
+ * Clears the current module options and adds the options which will be passed to JBoss Modules.
+ *
+ * Note that {@code -mp} or {@code --modulepath} is not supported. Use {@link #addModuleDirs(Iterable)} to add a
+ * module directory.
+ *
+ *
+ * @param args the argument to use
+ *
+ * @return the builder
+ */
+ public JBossModulesCommandBuilder setModuleOptions(final Iterable args) {
+ moduleOpts.clear();
+ addModuleOptions(args);
+ return this;
+ }
+
+ /**
+ * Sets the Java home where the Java executable can be found.
+ *
+ * @param javaHome the Java home or {@code null} to use te system property {@code java.home}
+ *
+ * @return the builder
+ */
+ public JBossModulesCommandBuilder setJavaHome(final String javaHome) {
+ environment.setJvm(Jvm.of(javaHome));
+ return this;
+ }
+
+ /**
+ * Sets the Java home where the Java executable can be found.
+ *
+ * @param javaHome the Java home or {@code null} to use te system property {@code java.home}
+ *
+ * @return the builder
+ */
+ public JBossModulesCommandBuilder setJavaHome(final Path javaHome) {
+ environment.setJvm(Jvm.of(javaHome));
+ return this;
+ }
+
+ /**
+ * Set to {@code true} to use JBoss Modules lockless mode.
+ *
+ * @param b {@code true} to use lockless mode
+ *
+ * @return the builder
+ */
+ public JBossModulesCommandBuilder setModulesLockless(final boolean b) {
+ if (b) {
+ modulesLocklessArg = "-Djboss.modules.lockless=true";
+ } else {
+ modulesLocklessArg = null;
+ }
+ return this;
+ }
+
+ /**
+ * Set to {@code true} to gather metrics for JBoss Modules.
+ *
+ * @param b {@code true} to gather metrics for JBoss Modules.
+ *
+ * @return this builder
+ */
+ public JBossModulesCommandBuilder setModulesMetrics(final boolean b) {
+ if (b) {
+ modulesMetricsArg = "-Djboss.modules.metrics=true";
+ } else {
+ modulesMetricsArg = null;
+ }
+ return this;
+ }
+
+ @Override
+ public List buildArguments() {
+ final List cmd = new ArrayList<>();
+ // Check to see if an agent was added as a module option, if so we want to add JBoss Modules as an agent.
+ if (addModuleAgent) {
+ cmd.add("-javaagent:" + getModulesJarName());
+ }
+ cmd.addAll(getJavaOptions());
+ if (environment.getJvm().isModular()) {
+ cmd.addAll(DEFAULT_MODULAR_VM_ARGUMENTS);
+ for (final String optionalModularArgument : OPTIONAL_DEFAULT_MODULAR_VM_ARGUMENTS) {
+ if (Jvm.isPackageAvailable(environment.getJvm().getPath(), optionalModularArgument)) {
+ cmd.add(optionalModularArgument);
+ }
+ }
+ }
+ if (environment.getJvm().enhancedSecurityManagerAvailable()) {
+ cmd.add(SECURITY_MANAGER_PROP_WITH_ALLOW_VALUE);
+ }
+ // Add these to JVM level system properties
+ if (modulesLocklessArg != null) {
+ cmd.add(modulesLocklessArg);
+ }
+ if (modulesMetricsArg != null) {
+ cmd.add(modulesMetricsArg);
+ }
+ cmd.add("-jar");
+ cmd.add(getModulesJarName());
+ if (useSecurityManager()) {
+ cmd.add(SECURITY_MANAGER_ARG);
+ }
+ // Add the agent argument for jboss-modules
+ cmd.addAll(moduleOpts);
+ cmd.add("-mp");
+ cmd.add(getModulePaths());
+ cmd.add(moduleName);
+
+ cmd.addAll(getServerArguments());
+ return cmd;
+ }
+
+ @Override
+ public List build() {
+ final List cmd = new ArrayList<>();
+ cmd.add(environment.getJvm().getCommand());
+ cmd.addAll(buildArguments());
+ return cmd;
+ }
+
+ protected void setSingleServerArg(final String key, final String value) {
+ serverArgs.set(key, value);
+ }
+
+ protected void addServerArg(final String key, final String value) {
+ serverArgs.add(key, value);
+ }
+
+ /**
+ * Returns the first argument from the server arguments.
+ *
+ * @param key the key to the argument
+ *
+ * @return the first argument or {@code null}
+ */
+ protected String getServerArg(final String key) {
+ return serverArgs.get(key);
+ }
+
+ /**
+ * Allows the subclass to do additional checking on whether the server argument should be added or not. In some
+ * cases it may be desirable for the argument passed to be added or processed elsewhere.
+ *
+ * @param argument the argument to test
+ *
+ * @return {@code true} if the argument should be added to the server arguments, {@code false} if the argument is
+ * handled by the subclass
+ */
+ boolean addServerArgument(final Argument argument) {
+ return true;
+ }
+
+ static boolean isJavaSecurityManagerConfigured(final Argument argument) {
+ return !ALLOW_VALUE.equals(argument.getValue()) && !DISALLOW_VALUE.equals(argument.getValue());
+ }
+}
diff --git a/launcher/src/main/java/org/wildfly/core/launcher/Launcher.java b/launcher/src/main/java/org/wildfly/core/launcher/Launcher.java
index 8613095c955..677818c1fcd 100644
--- a/launcher/src/main/java/org/wildfly/core/launcher/Launcher.java
+++ b/launcher/src/main/java/org/wildfly/core/launcher/Launcher.java
@@ -21,6 +21,7 @@
*
* @author James R. Perkins
*/
+@SuppressWarnings("unused")
public class Launcher {
private final CommandBuilder builder;
@@ -187,7 +188,7 @@ public Launcher setDirectory(final File dir) {
* @see java.lang.ProcessBuilder#directory(java.io.File)
*/
public Launcher setDirectory(final String dir) {
- return setDirectory(AbstractCommandBuilder.validateAndNormalizeDir(dir, true));
+ return setDirectory(Environment.validateAndNormalizeDir(dir, true));
}
/**
diff --git a/launcher/src/main/java/org/wildfly/core/launcher/ProcessHelper.java b/launcher/src/main/java/org/wildfly/core/launcher/ProcessHelper.java
index eec58ecf4a8..6520fc81d98 100644
--- a/launcher/src/main/java/org/wildfly/core/launcher/ProcessHelper.java
+++ b/launcher/src/main/java/org/wildfly/core/launcher/ProcessHelper.java
@@ -18,15 +18,12 @@ public class ProcessHelper {
* @param process the process to check
*
* @return {@code true} if the process has died, otherwise {@code false}
+ * @see Process#isAlive()
*/
+ @SuppressWarnings("unused")
+ @Deprecated(forRemoval = true)
public static boolean processHasDied(final Process process) {
- try {
- // The process is still running
- process.exitValue();
- return true;
- } catch (IllegalThreadStateException ignore) {
- }
- return false;
+ return !process.isAlive();
}
/**
@@ -54,16 +51,13 @@ public static int destroyProcess(final Process process) throws InterruptedExcept
* java.lang.RuntimePermission RuntimePermission("shutdownHooks")
}
*/
public static Thread addShutdownHook(final Process process) {
- final Thread thread = new Thread(new Runnable() {
- @Override
- public void run() {
- if (process != null) {
- process.destroy();
- try {
- process.waitFor();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
+ final Thread thread = new Thread(() -> {
+ if (process != null) {
+ process.destroyForcibly();
+ try {
+ process.waitFor();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
}
}
});
diff --git a/launcher/src/main/java/org/wildfly/core/launcher/StandaloneCommandBuilder.java b/launcher/src/main/java/org/wildfly/core/launcher/StandaloneCommandBuilder.java
index 2d8e643f993..a0a18953999 100644
--- a/launcher/src/main/java/org/wildfly/core/launcher/StandaloneCommandBuilder.java
+++ b/launcher/src/main/java/org/wildfly/core/launcher/StandaloneCommandBuilder.java
@@ -24,12 +24,13 @@
*
* @author James R. Perkins
*/
-@SuppressWarnings({"unused", "MagicNumber", "UnusedReturnValue"})
+@SuppressWarnings({"unused", "UnusedReturnValue"})
public class StandaloneCommandBuilder extends AbstractCommandBuilder implements CommandBuilder {
// JPDA remote socket debugging
static final String DEBUG_FORMAT = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=%s,address=%d";
+ private static final String MODULE_NAME = "org.jboss.as.standalone";
private static final String SERVER_BASE_DIR = "jboss.server.base.dir";
private static final String SERVER_CONFIG_DIR = "jboss.server.config.dir";
private static final String SERVER_LOG_DIR = "jboss.server.log.dir";
@@ -52,7 +53,7 @@ public class StandaloneCommandBuilder extends AbstractCommandBuilder();
@@ -334,7 +335,7 @@ public StandaloneCommandBuilder setDebug(final boolean suspend, final int port)
* @return the builder
*/
public StandaloneCommandBuilder setBaseDirectory(final String baseDir) {
- this.baseDir = validateAndNormalizeDir(baseDir, true);
+ this.baseDir = Environment.validateAndNormalizeDir(baseDir, true);
return this;
}
@@ -348,7 +349,7 @@ public StandaloneCommandBuilder setBaseDirectory(final String baseDir) {
* @return the builder
*/
public StandaloneCommandBuilder setBaseDirectory(final Path baseDir) {
- this.baseDir = validateAndNormalizeDir(baseDir, true);
+ this.baseDir = Environment.validateAndNormalizeDir(baseDir, true);
return this;
}
@@ -574,7 +575,7 @@ public List buildArguments() {
if (environment.getJvm().isModular()) {
cmd.addAll(DEFAULT_MODULAR_VM_ARGUMENTS);
for (final String optionalModularArgument : OPTIONAL_DEFAULT_MODULAR_VM_ARGUMENTS) {
- if (environment.getJvm().isPackageAvailable(environment.getJvm().getPath(), optionalModularArgument)) {
+ if (Jvm.isPackageAvailable(environment.getJvm().getPath(), optionalModularArgument)) {
cmd.add(optionalModularArgument);
}
}
@@ -607,7 +608,7 @@ public List buildArguments() {
cmd.addAll(moduleOpts);
cmd.add("-mp");
cmd.add(getModulePaths());
- cmd.add("org.jboss.as.standalone");
+ cmd.add(MODULE_NAME);
// Add the security properties
StringBuilder sb = new StringBuilder(64);
@@ -624,14 +625,6 @@ public List buildArguments() {
return cmd;
}
- @Override
- public List build() {
- final List cmd = new ArrayList<>();
- cmd.add(environment.getJvm().getCommand());
- cmd.addAll(buildArguments());
- return cmd;
- }
-
@Override
public Path getJavaHome() {
return environment.getJvm().getPath();
diff --git a/launcher/src/test/java/org/wildfly/core/launcher/CommandBuilderTest.java b/launcher/src/test/java/org/wildfly/core/launcher/CommandBuilderTest.java
index 5c724c61752..9c9c360c68e 100644
--- a/launcher/src/test/java/org/wildfly/core/launcher/CommandBuilderTest.java
+++ b/launcher/src/test/java/org/wildfly/core/launcher/CommandBuilderTest.java
@@ -39,6 +39,41 @@ public class CommandBuilderTest {
}
}
+ @Test
+ public void testJBossModulesBuilder() {
+ // Set up a standalone command builder
+ final JBossModulesCommandBuilder commandBuilder = JBossModulesCommandBuilder.of(WILDFLY_HOME, "org.jboss.as.launcher.test")
+ .addJavaOption("-Djava.security.manager")
+ .addJavaOption("-Djava.net.preferIPv4Stack=true")
+ .addJavaOption("-Djava.net.preferIPv4Stack=false")
+ .addModuleOption("-javaagent:test-agent1.jar")
+ .addServerArgument("--server=test");
+
+ // Get all the commands
+ List commands = commandBuilder.buildArguments();
+
+ Assert.assertTrue("Missing -secmgr option", commands.contains("-secmgr"));
+
+ Assert.assertTrue("Missing jboss-modules.jar", commands.stream().anyMatch(entry -> entry.matches("-javaagent:.*jboss-modules.jar$")));
+ Assert.assertTrue("Missing test-agent1.jar", commands.contains("-javaagent:test-agent1.jar"));
+ Assert.assertTrue("Missing --server=test", commands.contains("--server=test"));
+
+ // If we're using Java 9+ ensure the modular JDK options were added
+ testModularJvmArguments(commands, 1);
+
+ // A system property should only be added ones
+ long count = 0L;
+ for (String s : commandBuilder.getJavaOptions()) {
+ if (s.contains("java.net.preferIPv4Stack")) {
+ count++;
+ }
+ }
+ Assert.assertEquals("There should be only one java.net.preferIPv4Stack system property", 1, count);
+
+ // The value saved should be the last value added
+ Assert.assertTrue("java.net.preferIPv4Stack should be set to false", commandBuilder.getJavaOptions().contains("-Djava.net.preferIPv4Stack=false"));
+ }
+
@Test
public void testStandaloneBuilder() {
// Set up a standalone command builder