diff --git a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/CLIBootstrap.java b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/CLIBootstrap.java index 3f2b4376cdc..942091df07e 100644 --- a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/CLIBootstrap.java +++ b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/CLIBootstrap.java @@ -37,37 +37,36 @@ * only if the new code is made subject to such option by the copyright * holder. */ - +// Portions Copyright [2019] [Payara Foundation and/or its affiliates] package org.glassfish.appclient.client; -import com.sun.enterprise.util.JDK; -import com.sun.enterprise.util.LocalStringManager; -import com.sun.enterprise.util.LocalStringManagerImpl; -import com.sun.enterprise.util.OS; +import static java.util.Arrays.asList; + import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; + import org.glassfish.appclient.client.acc.UserError; +import com.sun.enterprise.util.JDK; +import com.sun.enterprise.util.OS; + /** * - * Constructs a java command to launch the ACC with the correct agent and - * command line arguments, based on the current operating environment and - * the user's own command-line arguments. + * Constructs a java command to launch the ACC with the correct agent and command line arguments, based on the current + * operating environment and the user's own command-line arguments. *

- * The user might have specified JVM options as well as ACC options as - * well as arguments to be passed to the client. Further, we need to make - * sure that the GlassFish extension libraries directories and endorsed - * directories are included in java.ext.dirs and java.endorsed.dirs, - * regardless of whether the user specified any explicitly. + * The user might have specified JVM options as well as ACC options as well as arguments to be passed to the client. + * Further, we need to make sure that the GlassFish extension libraries directories and endorsed directories are + * included in java.ext.dirs and java.endorsed.dirs, regardless of whether the user specified any explicitly. *

- * This program emits a java command line that will run the ACC so that it - * will launch the client. The emitted command will need to look like this: + * This program emits a java command line that will run the ACC so that it will launch the client. The emitted command + * will need to look like this: + * *

  * {@code
  * java \
@@ -76,21 +75,19 @@
  *   -javaagent:(path-to-gf-client.jar)=(option string for our agent) \
  *   (main class setting: "-jar x.jar" or "a.b.Main" or "path-to-file.class")
  *   (arguments to be passed to the client)
- * }
+ * } + * *

- * The general design of this class uses several inner classes, CommandLineElement - * and its extensions. These classes have slightly different behavior depending - * on the specific type of command line element each represents. Each has - * a regex pattern which it uses to decide whether it recognizes a particular - * command line element or not. Each also implements (or inherits) the - * processValue method which actually consumes the command line element being - * handled -- and sometimes the next one as well if the element takes a value - * (such as -classpath). + * The general design of this class uses several inner classes, CommandLineElement and its extensions. These classes + * have slightly different behavior depending on the specific type of command line element each represents. Each has a + * regex pattern which it uses to decide whether it recognizes a particular command line element or not. Each also + * implements (or inherits) the processValue method which actually consumes the command line element being handled -- + * and sometimes the next one as well if the element takes a value (such as -classpath). * * @author Tim Quinn */ public class CLIBootstrap { - + public final static String FILE_OPTIONS_INTRODUCER = "argsfile="; private final static String COMMA_IN_ARG_PLACEHOLDER = "+-+-+-+"; @@ -100,42 +97,29 @@ public class CLIBootstrap { final static String ENV_VAR_PROP_PREFIX = "acc."; /** options to the ACC that take a value */ - private final static String ACC_VALUED_OPTIONS_PATTERN = - "-mainclass|-name|-xml|-configxml|-user|-password|-passwordfile|-targetserver"; + private final static String ACC_VALUED_OPTIONS_PATTERN = "-mainclass|-name|-xml|-configxml|-user|-password|-passwordfile|-targetserver"; /** options to the ACC that take no value */ - private final static String ACC_UNVALUED_OPTIONS_PATTERN = - "-textauth|-noappinvoke|-usage|-help"; - - private final static String JVM_VALUED_OPTIONS_PATTERN = - "-classpath|-cp"; - + private final static String ACC_UNVALUED_OPTIONS_PATTERN = "-textauth|-noappinvoke|-usage|-help|-debug"; + private final static String JVM_VALUED_OPTIONS_PATTERN = "-classpath|-cp"; private final static String INSTALL_ROOT_PROPERTY_EXPR = "-Dcom.sun.aas.installRoot="; private final static String SECURITY_POLICY_PROPERTY_EXPR = "-Djava.security.policy="; private final static String SECURITY_AUTH_LOGIN_CONFIG_PROPERTY_EXPR = "-Djava.security.auth.login.config="; - private final static String SYSTEM_CLASS_LOADER_PROPERTY_EXPR = - "-Djava.system.class.loader=org.glassfish.appclient.client.acc.agent.ACCAgentClassLoader"; + private final static String SYSTEM_CLASS_LOADER_PROPERTY_EXPR = "-Djava.system.class.loader=org.glassfish.appclient.client.acc.agent.ACCAgentClassLoader"; - private final static String[] ENV_VARS = { - "_AS_INSTALL", "APPCPATH", "VMARGS"}; + private final static String[] ENV_VARS = { "_AS_INSTALL", "APPCPATH", "VMARGS" }; private final static String EXT_DIRS_INTRODUCER = "-Djava.ext.dirs"; private final static String ENDORSED_DIRS_INTRODUCER = "-Djava.endorsed.dirs"; - private static final LocalStringManager localStrings = new LocalStringManagerImpl(CLIBootstrap.class); - private JavaInfo java; - private GlassFishInfo gfInfo; - private UserVMArgs userVMArgs; /** * set up during init with various subtypes of command line elements */ - private CommandLineElement - extDirs, endorsedDirs, accValuedOptions, accUnvaluedOptions, - jvmPropertySettings, jvmValuedOptions, otherJVMOptions, arguments; + private CommandLineElement extDirs, endorsedDirs, accValuedOptions, accUnvaluedOptions, jvmPropertySettings, jvmValuedOptions, otherJVMOptions, arguments; /** arguments passed to the ACC Java agent */ private final AgentArgs agentArgs = new AgentArgs(); @@ -145,9 +129,9 @@ public class CLIBootstrap { /** command line elements from most specific to least specific matching pattern */ private CommandLineElement[] elementsInScanOrder; - - /** command line elements in the order they should appear on the generated - * command line + + /** + * command line elements in the order they should appear on the generated command line */ private CommandLineElement[] elementsInOutputOrder; @@ -156,31 +140,25 @@ public class CLIBootstrap { */ public static void main(String[] args) { try { - /* - * Convert env vars to properties. (This makes testing easier.) - */ + //Convert env vars to properties. (This makes testing easier.) envToProps(); - final CLIBootstrap boot = new CLIBootstrap(); - /* - * Because of how Windows passes arguments, the calling Windows - * script assigned the input arguments to an environment variable. - * Parse that variable's value into the actual arguments. - */ + + // Because of how Windows passes arguments, the calling Windows script assigned the input arguments to an environment + // variable. Parse that variable's value into the actual arguments. if (INPUT_ARGS != null) { args = convertInputArgsVariable(INPUT_ARGS); } - final String outputCommandLine = boot.run(args); + + String outputCommandLine = new CLIBootstrap().run(args); if (isDebug) { System.err.println(outputCommandLine); } - /* - * Write the generated java command to System.out. The calling - * shell script will execute this command. - * - * Using print instead of println seems to work better. Using - * println added a \r to the end of the last command-line argument - * on Windows under cygwin. - */ + + // Write the generated java command to System.out. The calling shell script will execute this command. + // + // Using print instead of println seems to work better. Using println added a \r to the end of the last command-line + // argument on Windows under cygwin. + // System.out.print(outputCommandLine); } catch (Exception ex) { ex.printStackTrace(); @@ -191,37 +169,35 @@ public static void main(String[] args) { } /** - * Replaces commas in an argument value (which can confuse the ACC agent - * argument parsing because shells strip out double-quotes) with a special - * sequence. + * Replaces commas in an argument value (which can confuse the ACC agent argument parsing because shells strip out + * double-quotes) with a special sequence. * - * @param s string to encode + * @param input string to encode * @return encoded string */ - public static String encodeArg(final String s) { - return s.replace(",", COMMA_IN_ARG_PLACEHOLDER); + public static String encodeArg(String input) { + return input.replace(",", COMMA_IN_ARG_PLACEHOLDER); } /** * Replaces occurrences of comma encoding with commas. * - * @param s possibly encoded string + * @param input possibly encoded string * @return decoded string */ - public static String decodeArg(final String s) { - return s.replace(COMMA_IN_ARG_PLACEHOLDER, ","); + public static String decodeArg(String input) { + return input.replace(COMMA_IN_ARG_PLACEHOLDER, ","); } - private static String[] convertInputArgsVariable(final String inputArgs) { + private static String[] convertInputArgsVariable(String inputArgs) { /* - * The pattern matches a quoted string (double quotes around a string - * containing no double quote) or a non-quoted string (a string containing - * no white space or quotes). + * The pattern matches a quoted string (double quotes around a string containing no double quote) or a non-quoted string + * (a string containing no white space or quotes). */ - final Pattern argPattern = Pattern.compile("\"([^\"]+)\"|([^\"\\s]+)"); + Pattern argPattern = Pattern.compile("\"([^\"]+)\"|([^\"\\s]+)"); - final Matcher matcher = argPattern.matcher(inputArgs); - final List argList = new ArrayList(); + Matcher matcher = argPattern.matcher(inputArgs); + List argList = new ArrayList(); while (matcher.find()) { final String arg = (matcher.group(1) != null ? matcher.group(1) : matcher.group(2)); argList.add(arg); @@ -229,12 +205,13 @@ private static String[] convertInputArgsVariable(final String inputArgs) { System.err.println("Captured argument " + arg); } } + return argList.toArray(new String[argList.size()]); } private static void envToProps() { for (String envVar : ENV_VARS) { - final String value = System.getenv(envVar); + String value = System.getenv(envVar); if (value != null) { System.setProperty(ENV_VAR_PROP_PREFIX + envVar, value); if (isDebug) { @@ -245,18 +222,14 @@ private static void envToProps() { } CLIBootstrap() throws UserError { - init(); - } - - private void init() throws UserError { - java = initJava(); + java = new JavaInfo(); gfInfo = new GlassFishInfo(); userVMArgs = new UserVMArgs(System.getProperty(ENV_VAR_PROP_PREFIX + "VMARGS")); - /* - * Assign the various command line element matchers. See the - * descriptions of each subtype for what each is used for. - */ + // + // Assign the various command line element matchers. See the descriptions of each subtype for what each is used for. + // + extDirs = new OverridableDefaultedPathBasedOption( EXT_DIRS_INTRODUCER, userVMArgs.evExtDirs, @@ -270,30 +243,23 @@ private void init() throws UserError { gfInfo.endorsedPaths()); accValuedOptions = new ACCValuedOption(ACC_VALUED_OPTIONS_PATTERN); - accUnvaluedOptions = new ACCUnvaluedOption(ACC_UNVALUED_OPTIONS_PATTERN); - jvmPropertySettings = new JVMOption("-D.*", userVMArgs.evJVMPropertySettings); - - jvmValuedOptions = new JVMValuedOption(JVM_VALUED_OPTIONS_PATTERN, - userVMArgs.evJVMValuedOptions); - + jvmValuedOptions = new JVMValuedOption(JVM_VALUED_OPTIONS_PATTERN, userVMArgs.evJVMValuedOptions); otherJVMOptions = new JVMOption("-.*", userVMArgs.evOtherJVMOptions); - arguments = new CommandLineElement(".*", Pattern.DOTALL); initCommandLineElements(); } /** - * Populates the command line elements collection to contain the elements - * from most specific matching pattern to least specific. + * Populates the command line elements collection to contain the elements from most specific matching pattern to least + * specific. */ private void initCommandLineElements() { /* - * Add the elements in this order so the regex patterns will match - * the correct elements. In this arrangement, the patterns are from - * most specific to most general. + * Add the elements in this order so the regex patterns will match the correct elements. In this arrangement, the + * patterns are from most specific to most general. */ elementsInScanOrder = new CommandLineElement[] { extDirs, @@ -304,27 +270,23 @@ private void initCommandLineElements() { jvmPropertySettings, jvmMainSetting, otherJVMOptions, - arguments}; - + arguments }; + /* - * Add the elements in this order so they appear in the generated - * java command in the correct positions. + * Add the elements in this order so they appear in the generated java command in the correct positions. */ - //In JDK 9 and later ext and endorsed directory removed . + // In JDK 9 and later ext and endorsed directory removed . int major = JDK.getMajor(); - if(major >= 9) { - elementsInOutputOrder = new CommandLineElement[]{ + if (major >= 9) { + elementsInOutputOrder = new CommandLineElement[] { jvmValuedOptions, jvmPropertySettings, otherJVMOptions, accUnvaluedOptions, accValuedOptions, jvmMainSetting, - arguments - }; - } - else - { + arguments }; + } else { elementsInOutputOrder = new CommandLineElement[] { jvmValuedOptions, jvmPropertySettings, @@ -334,37 +296,34 @@ private void initCommandLineElements() { accUnvaluedOptions, accValuedOptions, jvmMainSetting, - arguments - }; + arguments }; } } /** - * Places double quote marks around a string if the string is not already - * so enclosed. - * @param s + * Places double quote marks around a string if the string is not already so enclosed. + * + * @param input * @return the string wrapped in double quotes if not already that way; the original string otherwise */ - private static String quote(final String s) { - if (s.length() > 2 && s.charAt(0) != '"' && s.charAt(s.length() - 1) != '"' ) { - return '\"' + s + '\"'; - } else { - return s; + private static String quote(String input) { + if (input.length() > 2 && input.charAt(0) != '"' && input.charAt(input.length() - 1) != '"') { + return '\"' + input + '\"'; } + + return input; } /** - * Quotes the string, on non-Windows systems quoting individually any - * $. The shell will have replaced any env. var. placeholders with - * their values before invoking this program. Anything that looks like a - * placeholder now is an odd but legal name that should not be substituted - * again. + * Quotes the string, on non-Windows systems quoting individually any $. The shell will have replaced any env. var. + * placeholders with their values before invoking this program. Anything that looks like a placeholder now is an odd but + * legal name that should not be substituted again. * * @param s * @return */ private static String quoteSuppressTokenSubst(final String s) { - return (OS.isWindows() ? quote(s) : quote(s.replace("$", "\\$"))); + return OS.isWindows() ? quote(s) : quote(s.replace("$", "\\$")); } /** @@ -375,27 +334,29 @@ private static class AgentArgs { private char sep = ','; AgentArgs() { - final String appcPath = System.getProperty(ENV_VAR_PROP_PREFIX + "APPCPATH"); + String appcPath = System.getProperty(ENV_VAR_PROP_PREFIX + "APPCPATH"); if (appcPath != null && appcPath.length() > 0) { add("appcpath=" + quote(appcPath)); } } - /** - * Adds an item to the Java agent arguments. - * @param item - */ - final void add(final String item) { - args.append(sep).append(item); - } - /** * Adds an ACC argument to the Java agent arguments. + * * @param accArg */ final void addACCArg(final String accArg) { add("arg=" + encodeArg(accArg)); } + + /** + * Adds an item to the Java agent arguments. + * + * @param item + */ + final void add(final String item) { + args.append(sep).append(item); + } @Override public String toString() { @@ -404,17 +365,15 @@ public String toString() { } /** - * A command-line element. Various subtypes have some different behavior - * for some of the methods. + * A command-line element. Various subtypes have some different behavior for some of the methods. */ private class CommandLineElement { private final Pattern pattern; - Matcher matcher; private final Pattern whiteSpacePattern = Pattern.compile("[\\r\\n]"); - /** allows multiple values; not all command line elements support this*/ + /** allows multiple values; not all command line elements support this */ final List values = new ArrayList(); CommandLineElement(String patternString) { @@ -425,42 +384,40 @@ private class CommandLineElement { pattern = Pattern.compile(patternString, flags); } - final boolean matchesPattern(final String element) { - matcher = pattern.matcher(element); - return matcher.matches(); - } - - boolean matches(final String element) { + boolean matches(String element) { return matchesPattern(element); } + + final boolean matchesPattern(final String element) { + return pattern.matcher(element).matches(); + } /** * Processes the command line element at args[slot]. *

* Subclass implementations might consume the next element as well. + * * @param args * @param slot * @return next slot to be processed - * @throws UserError if the user specified an option that requires a - * value but provided no value (either the next command line element is - * another option or there is no next element) + * @throws UserError if the user specified an option that requires a value but provided no value (either the next + * command line element is another option or there is no next element) */ int processValue(String[] args, int slot) throws UserError { - /* - * Ignore an argument that is just unquoted white space. - */ - final Matcher m = whiteSpacePattern.matcher(args[slot]); - if ( ! m.matches()) { + + // Ignore an argument that is just unquoted white space. + + if (!whiteSpacePattern.matcher(args[slot]).matches()) { values.add(args[slot++]); } else { slot++; } + return slot; } - + /** - * Adds the command-line element to the Java agent arguments, if - * appropriate. + * Adds the command-line element to the Java agent arguments, if appropriate. * * @param element */ @@ -469,6 +426,7 @@ void addToAgentArgs(final String element) { /** * Returns whether there is a next argument. + * * @param args * @param currentSlot * @return @@ -478,21 +436,19 @@ boolean isNextArg(String[] args, int currentSlot) { } /** - * Returns the next argument in the array, without advancing - * the pointer into the array. + * Returns the next argument in the array, without advancing the pointer into the array. * * @param args * @param currentSlot * @return */ - String nextArg(String[] args, int currentSlot){ + String nextArg(String[] args, int currentSlot) { return args[currentSlot + 1]; } /** - * Makes sure that there is a next argument and that its value does - * not start with a "-" which would indicate an option, rather than - * the value for the option we are currently processing. + * Makes sure that there is a next argument and that its value does not start with a "-" which would indicate an option, + * rather than the value for the option we are currently processing. * * @param args * @param currentSlot @@ -505,27 +461,23 @@ void ensureNonOptionNextArg(final String[] args, final int currentSlot) throws U } /** - * Adds a representation for this command-line element to the output - * command line. + * Adds a representation for this command-line element to the output command line. * * @param commandLine - * @return true if any values from this command-line element - * was added to the command line, false otherwise + * @return true if any values from this command-line element was added to the command line, false otherwise */ boolean format(final StringBuilder commandLine) { return format(commandLine, true); } /** - * Adds a representation for this command-line element to the output - * command line, quoting the value if requested. + * Adds a representation for this command-line element to the output command line, quoting the value if requested. * * @param commandLine * @param useQuotes - * @return true if any values from this command-line element - * were added to the command line; false otherwise + * @return true if any values from this command-line element were added to the command line; false otherwise */ - boolean format(final StringBuilder commandLine, boolean useQuotes) { + boolean format(StringBuilder commandLine, boolean useQuotes) { boolean needSep = false; for (String value : values) { if (needSep) { @@ -534,13 +486,14 @@ boolean format(final StringBuilder commandLine, boolean useQuotes) { format(commandLine, useQuotes, value); needSep = true; } - return ! values.isEmpty(); + + return !values.isEmpty(); } /** - * Returns the separator character to be inserted in the emitted - * command line between values stored in the same instance of this - * command line element. + * Returns the separator character to be inserted in the emitted command line between values stored in the same instance + * of this command line element. + * * @return */ char valueSep() { @@ -548,15 +501,14 @@ char valueSep() { } /** - * Adds a representation for the specified value to the output - * command line, quoting the value if required and + * Adds a representation for the specified value to the output command line, quoting the value if required and + * * @param commandLine * @param useQuotes * @param v * @return */ - StringBuilder format(final StringBuilder commandLine, - final boolean useQuotes, final String v) { + StringBuilder format(StringBuilder commandLine, boolean useQuotes, String v) { if (commandLine.length() > 0) { commandLine.append(' '); } @@ -576,19 +528,16 @@ private class Option extends CommandLineElement { } /** - * A JVM command-line option. Only JVM options which appear before the - * main class setting are propagated to the output command line as - * JVM options. If they appear after the main class setting then they - * are treated as arguments to the client. + * A JVM command-line option. Only JVM options which appear before the main class setting are propagated to the output + * command line as JVM options. If they appear after the main class setting then they are treated as arguments to the + * client. *

- * This type of command line element can include values specified using - * the VMARGS environment variable. + * This type of command line element can include values specified using the VMARGS environment variable. * */ private class JVMOption extends Option { - - JVMOption(final String patternString, - final CommandLineElement vmargsJVMOptionElement) { + + JVMOption(String patternString, CommandLineElement vmargsJVMOptionElement) { super(patternString); if (vmargsJVMOptionElement != null) { values.addAll(vmargsJVMOptionElement.values); @@ -596,26 +545,23 @@ private class JVMOption extends Option { } @Override - boolean matches(final String element) { + boolean matches(String element) { /* - * Although the element might match the pattern (-.*) we do - * not treat this as JVM option if we have already processed + * Although the element might match the pattern (-.*) we do not treat this as JVM option if we have already processed * the main class determinant. */ - return ( ! jvmMainSetting.isSet()) && super.matches(element); + return (!jvmMainSetting.isSet()) && super.matches(element); } } /** - * ACC options match anywhere on the command line unless and until we - * see "-jar xxx" in which case we impose the Java-style restriction that - * anything which follows the specification of the main class is an - * argument to be passed to the application. + * ACC options match anywhere on the command line unless and until we see "-jar xxx" in which case we impose the + * Java-style restriction that anything which follows the specification of the main class is an argument to be passed to + * the application. *

- * We do not impose the same restriction if the user specified -client xxx.jar - * in order to preserve backward compatibility with earlier releases, in - * which ACC options and client arguments could be intermixed anywhere on - * the command line. + * We do not impose the same restriction if the user specified -client xxx.jar in order to preserve backward + * compatibility with earlier releases, in which ACC options and client arguments could be intermixed anywhere on the + * command line. */ private class ACCUnvaluedOption extends Option { ACCUnvaluedOption(final String patternString) { @@ -623,22 +569,21 @@ private class ACCUnvaluedOption extends Option { } @Override - boolean matches(final String element) { - return ( ! jvmMainSetting.isJarSetting()) && super.matches(element); + boolean matches(String element) { + return (!jvmMainSetting.isJarSetting()) && super.matches(element); } @Override int processValue(String[] args, int slot) throws UserError { - final int result = super.processValue(args, slot); + int result = super.processValue(args, slot); agentArgs.addACCArg(values.get(values.size() - 1)); return result; } @Override - boolean format(final StringBuilder commandLine) { + boolean format(StringBuilder commandLine) { /* - * We do not send ACC arguments to the Java command line. They - * are placed into the agent argument string instead. + * We do not send ACC arguments to the Java command line. They are placed into the agent argument string instead. */ return false; } @@ -664,7 +609,7 @@ class OptionValue { ValuedOption(final String patternString) { super(patternString); } - + @Override int processValue(String[] args, int slot) throws UserError { ensureNonOptionNextArg(args, slot); @@ -672,21 +617,20 @@ int processValue(String[] args, int slot) throws UserError { return slot; } - + @Override boolean format(final StringBuilder commandLine) { for (OptionValue ov : optValues) { format(commandLine, false /* useQuotes */, ov.option); format(commandLine, true /* useQuotes */, ov.value); } - return ! optValues.isEmpty(); + return !optValues.isEmpty(); } } private class JVMValuedOption extends ValuedOption { - JVMValuedOption(final String patternString, - final CommandLineElement vmargsJVMValuedOption) { + JVMValuedOption(final String patternString, final CommandLineElement vmargsJVMValuedOption) { super(patternString); if (vmargsJVMValuedOption != null) { values.addAll(vmargsJVMValuedOption.values); @@ -695,7 +639,7 @@ private class JVMValuedOption extends ValuedOption { @Override boolean matches(final String element) { - return ( ! jvmMainSetting.isJarSetting()) && super.matches(element); + return (!jvmMainSetting.isJarSetting()) && super.matches(element); } } @@ -709,38 +653,36 @@ private class ACCValuedOption extends ValuedOption { @Override boolean matches(final String element) { - return ( ! jvmMainSetting.isJarSetting()) && super.matches(element); + return (!jvmMainSetting.isJarSetting()) && super.matches(element); } @Override int processValue(String[] args, int slot) throws UserError { - final int result = super.processValue(args, slot); - final OptionValue newOptionValue = optValues.get(optValues.size() - 1); + int result = super.processValue(args, slot); + + OptionValue newOptionValue = optValues.get(optValues.size() - 1); agentArgs.addACCArg(newOptionValue.option); agentArgs.addACCArg(quote(newOptionValue.value)); + return result; } @Override boolean format(final StringBuilder commandLine) { /* - * We do not send ACC arguments to the Java command line. They - * are placed into the agent argument string instead. + * We do not send ACC arguments to the Java command line. They are placed into the agent argument string instead. */ return false; } } /** - * Command line element(s) with which the user specified the client - * to be run. Note that once "-jar xxx" is specified then all - * subsequent arguments are passed to the client as arguments. - * Once "-client xxx" is specified then subsequent arguments are treated - * as ACC options (if they match) or arguments to the client. + * Command line element(s) with which the user specified the client to be run. Note that once "-jar xxx" is specified + * then all subsequent arguments are passed to the client as arguments. Once "-client xxx" is specified then subsequent + * arguments are treated as ACC options (if they match) or arguments to the client. */ private class JVMMainOption extends CommandLineElement { - private static final String JVM_MAIN_PATTERN = - "-jar|-client|[^-][^\\s]*"; + private static final String JVM_MAIN_PATTERN = "-jar|-client|[^-][^\\s]*"; private String introducer = null; @@ -757,23 +699,20 @@ boolean isClientSetting() { } boolean isClassSetting() { - return ( ! isJarSetting() && ! isClientSetting() && isSet()); + return (!isJarSetting() && !isClientSetting() && isSet()); } boolean isSet() { - return ! values.isEmpty(); + return !values.isEmpty(); } @Override boolean matches(String element) { /* - * For backward compatibility, the -client element can appear - * multiple times with the last appearance overriding earlier ones. + * For backward compatibility, the -client element can appear multiple times with the last appearance overriding earlier + * ones. */ - return (( ! isSet()) || - ( (isClientSetting() && element.equals("-client"))) - ) - && super.matches(element); + return ((!isSet()) || ((isClientSetting() && element.equals("-client")))) && super.matches(element); } @Override @@ -784,9 +723,8 @@ int processValue(String[] args, int slot) throws UserError { values.clear(); /* - * If arg[slot] is -jar or -client we expect the - * next value to be the file. Make sure there is - * a next item and that it does not start with -. + * If arg[slot] is -jar or -client we expect the next value to be the file. Make sure there is a next item and that it + * does not start with -. */ if (args[slot].charAt(0) == '-') { if (nextLooksOK(args, slot)) { @@ -796,9 +734,8 @@ int processValue(String[] args, int slot) throws UserError { final File clientSpec = new File(path); if (clientSpec.isDirectory()) { /* - * Record in the agent args that the user is launching - * a directory. Set the main class launch info to - * launch the ACC JAR. + * Record in the agent args that the user is launching a directory. Set the main class launch info to launch the ACC + * JAR. */ agentArgs.add("client=dir=" + quote(clientSpec.getAbsolutePath())); introducer = "-jar"; @@ -806,10 +743,8 @@ int processValue(String[] args, int slot) throws UserError { } else { agentArgs.add("client=jar=" + quote(path)); /* - * The client path is not a directory. It should be a - * .jar or a .ear file. If an EAR, then we want Java to - * launch our ACC jar. If a JAR, then we will launch - * that JAR. + * The client path is not a directory. It should be a .jar or a .ear file. If an EAR, then we want Java to launch our + * ACC jar. If a JAR, then we will launch that JAR. */ if (path.endsWith(".ear")) { introducer = "-jar"; @@ -827,17 +762,16 @@ int processValue(String[] args, int slot) throws UserError { final int result = super.processValue(args, slot); agentArgs.add("client=class=" + values.get(values.size() - 1)); return result; - + } } - + @Override boolean format(final StringBuilder commandLine) { if (introducer != null) { /* - * In the generated command we always use "-jar" to indicate - * the JAR to be launched, even if the user specified "-client" - * on the appclient command line. + * In the generated command we always use "-jar" to indicate the JAR to be launched, even if the user specified + * "-client" on the appclient command line. */ super.format(commandLine, false /* useQuotes */, "-jar"); return super.format(commandLine, true /* useQuotes */); @@ -846,90 +780,78 @@ boolean format(final StringBuilder commandLine) { } private boolean nextLooksOK(final String[] args, final int slot) { - return (isNextArg(args, slot) && (args[slot+1].charAt(0) != '-')); + return (isNextArg(args, slot) && (args[slot + 1].charAt(0) != '-')); } } /** - * A JVM option that uses values from the GlassFish installation plus default - * value(s) from the Java installation. If the user specifies one of these - * options on the command line then we discard the Java installation values - * and append the GlassFish values to the user's values. + * A JVM option that uses values from the GlassFish installation plus default value(s) from the Java installation. If + * the user specifies one of these options on the command line then we discard the Java installation values and append + * the GlassFish values to the user's values. *

- * This is used for handling java.ext.dirs and java.endorsed.dirs property - * settings. If the user does not specify the property then the user would - * expect the Java-provided directories to be used. We need to - * specify the GlassFish ones, so that means we need combine the GlassFish - * ones and the default JVM ones explicitly. + * This is used for handling java.ext.dirs and java.endorsed.dirs property settings. If the user does not specify the + * property then the user would expect the Java-provided directories to be used. We need to specify the GlassFish ones, + * so that means we need combine the GlassFish ones and the default JVM ones explicitly. *

- * On the other hand, if the user specifies the property then the JVM - * defaults are out of play. We still need the GlassFish directories to be - * used though. + * On the other hand, if the user specifies the property then the JVM defaults are out of play. We still need the + * GlassFish directories to be used though. */ private class OverridableDefaultedPathBasedOption extends JVMOption { private final String defaultValue; private final List gfValues; private final String introducer; - private boolean hasCommandLineValueAppeared = false; - - OverridableDefaultedPathBasedOption(final String introducer, - final CommandLineElement settingsFromEnvVar, - final String defaultValue, - final String... gfValues) { + private boolean hasCommandLineValueAppeared; + + OverridableDefaultedPathBasedOption(String introducer, CommandLineElement settingsFromEnvVar, String defaultValue, String... gfValues) { super(introducer + "=.*", null); + /* - * Preload the values for this option from the ones the user - * provides in the environment variable, if any. These values - * will be overwritten if the user also provides values on the - * command line. + * Preload the values for this option from the ones the user provides in the environment variable, if any. These values + * will be overwritten if the user also provides values on the command line. */ if (settingsFromEnvVar != null) { values.addAll(settingsFromEnvVar.values); } this.introducer = introducer; this.defaultValue = defaultValue; - this.gfValues = Arrays.asList(gfValues); + this.gfValues = asList(gfValues); } @Override int processValue(String[] args, int slot) throws UserError { /* - * Once we see a user-provided value on the command line itself - * for the first time, clear out any pre-loaded values from the - * environment variable. + * Once we see a user-provided value on the command line itself for the first time, clear out any pre-loaded values from + * the environment variable. */ - if ( ! hasCommandLineValueAppeared) { + if (!hasCommandLineValueAppeared) { values.clear(); hasCommandLineValueAppeared = true; } - values.addAll(Arrays.asList(args[slot++].substring(introducer.length() + 1).split(java.pathSeparator()))); + values.addAll(asList(args[slot++].substring(introducer.length() + 1).split(java.pathSeparator()))); return slot; } - + @Override - boolean format(final StringBuilder commandLine) { - final List combinedValues = new ArrayList(); - /* - * - */ + boolean format(StringBuilder commandLine) { + List combinedValues = new ArrayList(); + if (values.isEmpty()) { - /* - * The user did not specify this property, so we use - * the GlassFish value(s) plus the JVM default. - */ + // The user did not specify this property, so we use the GlassFish value(s) plus the JVM default. + combinedValues.addAll(gfValues); combinedValues.add(defaultValue); } else { - /* - * The user did specify this property, so we use - * the user's value plus the GlassFish value(s). - */ + // The user did specify this property, so we use the user's value plus the GlassFish value(s). + combinedValues.addAll(values); combinedValues.addAll(gfValues); } + commandLine.append(introducer).append("="); + boolean needSep = false; + for (String value : combinedValues) { if (needSep) { commandLine.append(java.pathSeparator()); @@ -937,97 +859,97 @@ boolean format(final StringBuilder commandLine) { commandLine.append(quoteSuppressTokenSubst(value)); needSep = true; } + return true; } } /** - * Adds JVM properties for various ACC settings. - * @param command - */ - private void addProperties(final StringBuilder command) { - - command.append(' ').append(INSTALL_ROOT_PROPERTY_EXPR).append(quote(gfInfo.home().getAbsolutePath())); - command.append(' ').append(SECURITY_POLICY_PROPERTY_EXPR).append(quote(gfInfo.securityPolicy().getAbsolutePath())); - command.append(' ').append(SYSTEM_CLASS_LOADER_PROPERTY_EXPR); - command.append(' ').append(SECURITY_AUTH_LOGIN_CONFIG_PROPERTY_EXPR).append(quote(gfInfo.loginConfig().getAbsolutePath())); - - } - - /** - * Processes the user-provided command-line elements and creates the - * resulting output string. + * Processes the user-provided command-line elements and creates the resulting output string. * * @param args * @throws UserError */ private String run(String[] args) throws UserError { - - java = initJava(); + java = new JavaInfo(); gfInfo = new GlassFishInfo(); - final String[] augmentedArgs = new String[args.length + 2]; + String[] augmentedArgs = new String[args.length + 2]; augmentedArgs[0] = "-configxml"; augmentedArgs[1] = gfInfo.configxml().getAbsolutePath(); System.arraycopy(args, 0, augmentedArgs, 2, args.length); - /* - * Process each command-line argument by the first CommandLineElement - * which matches the argument. - */ - for (int i = 0; i < augmentedArgs.length; ) { + + // Process each command-line argument by the first CommandLineElement which matches the argument. + + for (int i = 0; i < augmentedArgs.length;) { boolean isMatched = false; - for (CommandLineElement cle : elementsInScanOrder) { - if (isMatched = cle.matches(augmentedArgs[i])) { - i = cle.processValue(augmentedArgs, i); + for (CommandLineElement commandLineElement : elementsInScanOrder) { + if (isMatched = commandLineElement.matches(augmentedArgs[i])) { + i = commandLineElement.processValue(augmentedArgs, i); break; } } - if ( ! isMatched) { + + if (!isMatched) { throw new UserError("arg " + i + " = " + augmentedArgs[i] + " not recognized"); } } - - final StringBuilder command = new StringBuilder(quote(java.javaExe)); + + StringBuilder command = new StringBuilder(quote(java.javaExe)); addProperties(command); + + if (isDebug()) { + addDebugAgentOption(); + } /* - * The user does not specify the -javaagent option we need, so we - * provide it here. (It is added to the appropriate command-line - * element object so, when formatted, that command-line element - * includes the -javaagent option.) + * The user does not specify the -javaagent option we need, so we provide it here. (It is added to the appropriate + * command-line element object so, when formatted, that command-line element includes the -javaagent option.) */ addAgentOption(); - + /* * If the user did not specify a client or usage or help then add the -usage option. */ - if ( ! jvmMainSetting.isSet() && - ! isHelp() && - ! isUsage()) { - accUnvaluedOptions.processValue(new String[] {"-usage"}, 0); + if (!jvmMainSetting.isSet() && !isHelp() && !isUsage()) { + accUnvaluedOptions.processValue(new String[] { "-usage" }, 0); } - + boolean needSep = true; - for (CommandLineElement e : elementsInOutputOrder) { - needSep = processCommandElement(command, e, needSep); + for (CommandLineElement commandLineElement : elementsInOutputOrder) { + needSep = processCommandElement(command, commandLineElement, needSep); } - + return command.toString(); } - private boolean processCommandElement( - final StringBuilder command, - final CommandLineElement e, - final boolean needSep) { + /** + * Adds JVM properties for various ACC settings. + * + * @param command + */ + private void addProperties(final StringBuilder command) { + command.append(' ') + .append(INSTALL_ROOT_PROPERTY_EXPR).append(quote(gfInfo.home().getAbsolutePath())) + .append(' ') + .append(SECURITY_POLICY_PROPERTY_EXPR).append(quote(gfInfo.securityPolicy().getAbsolutePath())) + .append(' ') + .append(SYSTEM_CLASS_LOADER_PROPERTY_EXPR) + .append(' ') + .append(SECURITY_AUTH_LOGIN_CONFIG_PROPERTY_EXPR).append(quote(gfInfo.loginConfig().getAbsolutePath())); + + } + + private boolean processCommandElement(final StringBuilder command, final CommandLineElement e, final boolean needSep) { if (needSep) { command.append(' '); } return e.format(command); } - + private boolean isHelp() { return accUnvaluedOptions.values.contains("-help"); } @@ -1035,54 +957,66 @@ private boolean isHelp() { private boolean isUsage() { return accUnvaluedOptions.values.contains("-usage"); } + + private boolean isDebug() { + return accUnvaluedOptions.values.contains("-debug"); + } /** * Adds the -javaagent option to the command line. * */ private void addAgentOption() throws UserError { - otherJVMOptions.processValue(new String[] { - "-javaagent:" + quote(gfInfo.agentJarPath()) + agentOptionsFromFile()}, - 0); + otherJVMOptions.processValue(new String[] { "-javaagent:" + quote(gfInfo.agentJarPath()) + agentOptionsFromFile() }, 0); } + /** + * Adds the -javaagent debug option to the command line. + * + */ + private void addDebugAgentOption() throws UserError { + otherJVMOptions.processValue(new String[] { "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"}, 0); + } + private String agentOptionsFromFile() { try { - final File argsFile = fileContainingAgentArgs(); - return '=' + FILE_OPTIONS_INTRODUCER + quote(argsFile.getAbsolutePath()); + return '=' + FILE_OPTIONS_INTRODUCER + quote(fileContainingAgentArgs().getAbsolutePath()); } catch (Exception ex) { throw new RuntimeException(ex); } } - + private File fileContainingAgentArgs() throws IOException { - final File argsFile = File.createTempFile("acc", ".dat"); - final PrintStream ps = new PrintStream(argsFile); - ps.println(agentArgs.toString()); - ps.close(); + File argsFile = File.createTempFile("acc", ".dat"); + + try (PrintStream printStream = new PrintStream(argsFile)) { + printStream.println(agentArgs.toString()); + } + return argsFile; } /** - * Encapsulates information about the GlassFish installation, mostly useful - * directories within the installation. + * Encapsulates information about the GlassFish installation, mostly useful directories within the installation. *

* Note that we use the property acc._AS_INSTALL to find the installation. */ static class GlassFishInfo { + + private static final String ACC_CONFIG_PREFIX = "domains/domain1/config"; private final File home; private final File modules; private final File lib; private final File libAppclient; - private static final String ACC_CONFIG_PREFIX = "domains/domain1/config"; GlassFishInfo() { - final String asInstallPath = System.getProperty(ENV_VAR_PROP_PREFIX + "_AS_INSTALL"); + String asInstallPath = System.getProperty(ENV_VAR_PROP_PREFIX + "_AS_INSTALL"); if (asInstallPath == null || asInstallPath.length() == 0) { throw new IllegalArgumentException("_AS_INSTALL == null"); } - this.home = new File(asInstallPath); + + home = new File(asInstallPath); modules = new File(home, "modules"); lib = new File(home, "lib"); libAppclient = new File(lib, "appclient"); @@ -1101,30 +1035,26 @@ File lib() { } File configxml() { - /* - * Try using glassfish-acc.xml. If that does not exist then the user - * might have done an in-place upgrade from an earlier version that - * used sun-acc.xml. - */ - final File configXMLFile = new File(new File(home, ACC_CONFIG_PREFIX), "glassfish-acc.xml"); + // Try using glassfish-acc.xml. If that does not exist then the user might have done an in-place upgrade from an earlier + // version that used sun-acc.xml. + + File configXMLFile = new File(new File(home, ACC_CONFIG_PREFIX), "glassfish-acc.xml"); if (configXMLFile.canRead()) { return configXMLFile; } - final File sunACCXMLFile = new File(new File(home, ACC_CONFIG_PREFIX), "sun-acc.xml"); + + File sunACCXMLFile = new File(new File(home, ACC_CONFIG_PREFIX), "sun-acc.xml"); if (sunACCXMLFile.canRead()) { return sunACCXMLFile; } - /* - * We found neither, but when an error is reported we want it to - * report the glassfish-acc.xml file is missing. - */ + + + // We found neither, but when an error is reported we want it to report the glassfish-acc.xml file is missing. return configXMLFile; } String[] endorsedPaths() { - return new String[] { - new File(lib, "endorsed").getAbsolutePath(), - new File(modules, "endorsed").getAbsolutePath()}; + return new String[] { new File(lib, "endorsed").getAbsolutePath(), new File(modules, "endorsed").getAbsolutePath() }; } String extPaths() { @@ -1143,46 +1073,31 @@ File loginConfig() { return new File(libAppclient, "appclientlogin.conf"); } } - - JavaInfo initJava() { - return new JavaInfo(); - } - + /** * Collects information about the current Java implementation. *

- * The user might have defined AS_JAVA or JAVA_HOME, or simply relied on - * the current PATH setting to choose which Java to use. Regardless, once - * this code is running SOME Java has been successfully chosen. Use - * the java.home property to find the JRE's home, which we need for the - * library directory (for example). + * The user might have defined AS_JAVA or JAVA_HOME, or simply relied on the current PATH setting to choose which Java + * to use. Regardless, once this code is running SOME Java has been successfully chosen. Use the java.home property to + * find the JRE's home, which we need for the library directory (for example). */ static class JavaInfo { - private final static String CYGWIN_PROP_NAME = "org.glassfish.isCygwin"; - private final static String SHELL_PROP_NAME = "org.glassfish.appclient.shell"; + private static final String SHELL_PROP_NAME = "org.glassfish.appclient.shell"; /* - * The appclient and appclient.bat scripts set ACCJava. - * Properties would be nicer instead of env vars, but the Windows - * script handling of command line args in the for statement treats - * the = in -Dprop=value as an argument separator and breaks the - * property assignment apart into two arguments. + * The appclient and appclient.bat scripts set ACCJava. Properties would be nicer instead of env vars, but the Windows + * script handling of command line args in the for statement treats the = in -Dprop=value as an argument separator and + * breaks the property assignment apart into two arguments. */ - private final static String ACCJava_ENV_VAR_NAME = "ACCJava"; - - private final boolean useWindowsSyntax = File.separatorChar == '\\' && - (System.getProperty(SHELL_PROP_NAME) == null); + private static final String ACCJava_ENV_VAR_NAME = "ACCJava"; + private final boolean useWindowsSyntax = File.separatorChar == '\\' && (System.getProperty(SHELL_PROP_NAME) == null); protected String javaExe; protected File jreHome; - private JavaInfo() { - init(); - } - - private void init() { + JavaInfo() { jreHome = new File(System.getProperty("java.home")); javaExe = javaExe(); } @@ -1217,20 +1132,17 @@ String pathSeparator() { } /** - * Handles user-specified VM arguments passed by the environment variable - * VMARGS. + * Handles user-specified VM arguments passed by the environment variable VMARGS. *

- * This is very much like the handling of the arguments on the more - * general command line, except that we expect only valid VM arguments - * here. + * This is very much like the handling of the arguments on the more general command line, except that we expect only + * valid VM arguments here. *

- * Some of the "main" CommandLineElements processed earlier in the class will - * use the inner command line elements here to augment the values they process. + * Some of the "main" CommandLineElements processed earlier in the class will use the inner command line elements here + * to augment the values they process. */ class UserVMArgs { - private CommandLineElement evExtDirs, evEndorsedDirs, - evJVMPropertySettings, evJVMValuedOptions, evOtherJVMOptions; + private CommandLineElement evExtDirs, evEndorsedDirs, evJVMPropertySettings, evJVMValuedOptions, evOtherJVMOptions; private final List evElements = new ArrayList(); @@ -1239,22 +1151,11 @@ class UserVMArgs { if (isDebug) { System.err.println("VMARGS = " + (vmargs == null ? "null" : vmargs)); } - evExtDirs = new OverridableDefaultedPathBasedOption( - EXT_DIRS_INTRODUCER, - null, - java.ext().getAbsolutePath(), - gfInfo.extPaths()); - - evEndorsedDirs = new OverridableDefaultedPathBasedOption( - ENDORSED_DIRS_INTRODUCER, - null, - java.endorsed().getAbsolutePath(), - gfInfo.endorsedPaths()); - + + evExtDirs = new OverridableDefaultedPathBasedOption(EXT_DIRS_INTRODUCER, null, java.ext().getAbsolutePath(), gfInfo.extPaths()); + evEndorsedDirs = new OverridableDefaultedPathBasedOption(ENDORSED_DIRS_INTRODUCER, null, java.endorsed().getAbsolutePath(), gfInfo.endorsedPaths()); evJVMPropertySettings = new JVMOption("-D.*", null); - evJVMValuedOptions = new JVMValuedOption(JVM_VALUED_OPTIONS_PATTERN, null); - evOtherJVMOptions = new JVMOption("-.*", null); initEVCommandLineElements(); @@ -1262,7 +1163,7 @@ class UserVMArgs { if (vmargs == null) { return; } - + processEVCommandLineElements(convertInputArgsVariable(vmargs)); } @@ -1276,18 +1177,17 @@ private void initEVCommandLineElements() { private void processEVCommandLineElements(final String[] envVarJVMArgs) throws UserError { /* - * Process each command-line argument by the first CommandLineElement - * which matches the argument. + * Process each command-line argument by the first CommandLineElement which matches the argument. */ - for (int i = 0; i < envVarJVMArgs.length; ) { + for (int i = 0; i < envVarJVMArgs.length;) { boolean isMatched = false; - for (CommandLineElement cle : evElements) { - if (isMatched = cle.matches(envVarJVMArgs[i])) { - i = cle.processValue(envVarJVMArgs, i); + for (CommandLineElement commandLineElement : evElements) { + if (isMatched = commandLineElement.matches(envVarJVMArgs[i])) { + i = commandLineElement.processValue(envVarJVMArgs, i); break; } } - if ( ! isMatched) { + if (!isMatched) { throw new UserError("arg " + i + " = " + envVarJVMArgs[i] + " not recognized"); } } diff --git a/appserver/appclient/client/acc/src/test/java/org/glassfish/appclient/client/CLIBootstrapTest.java b/appserver/appclient/client/acc/src/test/java/org/glassfish/appclient/client/CLIBootstrapTest.java index eca40d206a1..75f6316312f 100644 --- a/appserver/appclient/client/acc/src/test/java/org/glassfish/appclient/client/CLIBootstrapTest.java +++ b/appserver/appclient/client/acc/src/test/java/org/glassfish/appclient/client/CLIBootstrapTest.java @@ -37,9 +37,11 @@ * only if the new code is made subject to such option by the copyright * holder. */ - +// Portions Copyright [2019] [Payara Foundation and/or its affiliates] package org.glassfish.appclient.client; +import static org.junit.Assert.fail; + import org.glassfish.appclient.client.acc.UserError; import org.junit.After; import org.junit.AfterClass; @@ -47,7 +49,6 @@ import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import static org.junit.Assert.*; /** * @@ -111,7 +112,7 @@ private void runTestUsingBadLocation(final String envVarName) { final CLIBootstrap boot = new CLIBootstrap(); System.setProperty(CLIBootstrap.ENV_VAR_PROP_PREFIX + envVarName, "shouldnotexistanywhere"); - CLIBootstrap.JavaInfo javaInfo = boot.initJava(); + CLIBootstrap.JavaInfo javaInfo = new CLIBootstrap.JavaInfo(); } catch (UserError ex) { /* @@ -126,7 +127,7 @@ private void runTest(final String envVarName) { System.getProperty("java.home")); try { final CLIBootstrap boot = new CLIBootstrap(); - CLIBootstrap.JavaInfo javaInfo = boot.initJava(); + CLIBootstrap.JavaInfo javaInfo = new CLIBootstrap.JavaInfo(); if (javaInfo == null) { fail("chooseJava found no match; expected to match on " + envVarName); } diff --git a/nucleus/payara-modules/payara-executor-service/src/main/java/fish/payara/nucleus/executorservice/PayaraExecutorService.java b/nucleus/payara-modules/payara-executor-service/src/main/java/fish/payara/nucleus/executorservice/PayaraExecutorService.java index ef8cada8bda..135d422733f 100644 --- a/nucleus/payara-modules/payara-executor-service/src/main/java/fish/payara/nucleus/executorservice/PayaraExecutorService.java +++ b/nucleus/payara-modules/payara-executor-service/src/main/java/fish/payara/nucleus/executorservice/PayaraExecutorService.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright (c) [2017-2018] Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) [2017-2019] Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -39,7 +39,9 @@ */ package fish.payara.nucleus.executorservice; -import com.sun.enterprise.config.serverbeans.Config; +import static java.util.logging.Level.SEVERE; +import static org.glassfish.api.admin.ProcessEnvironment.ProcessType.ACC; + import java.beans.PropertyChangeEvent; import java.lang.Thread.UncaughtExceptionHandler; import java.util.ArrayList; @@ -52,14 +54,16 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; + import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.inject.Named; + +import org.glassfish.api.admin.ProcessEnvironment; import org.glassfish.api.admin.ServerEnvironment; import org.glassfish.api.event.EventListener; import org.glassfish.api.event.EventTypes; @@ -73,6 +77,8 @@ import org.jvnet.hk2.config.UnprocessedChangeEvent; import org.jvnet.hk2.config.UnprocessedChangeEvents; +import com.sun.enterprise.config.serverbeans.Config; + /** * * @author Andrew Pielage @@ -90,6 +96,9 @@ public class PayaraExecutorService implements ConfigListener, EventListener { @Inject ServerEnvironment serverEnvironment; + + @Inject + private ProcessEnvironment processEnvironment; @Inject private Events events; @@ -99,14 +108,12 @@ public class PayaraExecutorService implements ConfigListener, EventListener { @PostConstruct public void postConstruct() { - if (events != null) { events.register(this); } if (payaraExecutorServiceConfiguration == null) { - payaraExecutorServiceConfiguration = Globals.getDefaultHabitat() - .getService(PayaraExecutorServiceConfiguration.class); + payaraExecutorServiceConfiguration = Globals.get(PayaraExecutorServiceConfiguration.class); } if (transactions != null) { @@ -129,37 +136,64 @@ public void event(Event event) { } private void initialiseThreadPools() { - int threadPoolExecutorQueueSize = Integer.valueOf( - payaraExecutorServiceConfiguration.getThreadPoolExecutorQueueSize()); - if (threadPoolExecutorQueueSize > 0) { + if (isACC()) { + + // The application client container doesn't use the executor service locally for now. + // But create a "mock" executor to be absolutely sure. threadPoolExecutor = new ThreadPoolExecutor( - Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorCorePoolSize()), - Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorMaxPoolSize()), - Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorKeepAliveTime()), - TimeUnit.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorKeepAliveTimeUnit()), - new LinkedBlockingQueue<>(threadPoolExecutorQueueSize), - (Runnable r) -> new Thread(r, "payara-executor-service-task")); + 0, + 1, + 0, + TimeUnit.SECONDS, + new SynchronousQueue<>(), + r -> new Thread(r, "payara-executor-service-task")); + threadPoolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + + scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor( + 0, r -> { + Thread t = new Thread(r, "payara-executor-service-scheduled-task"); + t.setUncaughtExceptionHandler( (thread, thrwbl) -> + Logger.getLogger(PayaraExecutorService.class.getName()).log(SEVERE, "Uncaught exception in Payara Scheduled Executor thread ", thrwbl)); + return t; + }); + scheduledThreadPoolExecutor.setRemoveOnCancelPolicy(true); + + } else { - threadPoolExecutor = new ThreadPoolExecutor( - Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorCorePoolSize()), - Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorMaxPoolSize()), - Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorKeepAliveTime()), - TimeUnit.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorKeepAliveTimeUnit()), - new SynchronousQueue<>(), (Runnable r) -> new Thread(r, "payara-executor-service-task")); + int threadPoolExecutorQueueSize = Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorQueueSize()); + + if (threadPoolExecutorQueueSize > 0) { + threadPoolExecutor = new ThreadPoolExecutor( + Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorCorePoolSize()), + Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorMaxPoolSize()), + Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorKeepAliveTime()), + TimeUnit.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorKeepAliveTimeUnit()), + new LinkedBlockingQueue<>(threadPoolExecutorQueueSize), + (Runnable r) -> new Thread(r, "payara-executor-service-task")); + } else { + threadPoolExecutor = new ThreadPoolExecutor( + Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorCorePoolSize()), + Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorMaxPoolSize()), + Integer.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorKeepAliveTime()), + TimeUnit.valueOf(payaraExecutorServiceConfiguration.getThreadPoolExecutorKeepAliveTimeUnit()), + new SynchronousQueue<>(), (Runnable r) -> new Thread(r, "payara-executor-service-task")); + } + + threadPoolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor( + Integer.valueOf(payaraExecutorServiceConfiguration.getScheduledThreadPoolExecutorCorePoolSize()), (Runnable r) -> { + Thread t = new Thread(r, "payara-executor-service-scheduled-task"); + t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { + @Override + public void uncaughtException(Thread thread, Throwable thrwbl) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Uncaught exception in Payara Scheduled Executor thread ",thrwbl); + } + }); + return t; + }); + scheduledThreadPoolExecutor.setRemoveOnCancelPolicy(true); } - threadPoolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); - scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor( - Integer.valueOf(payaraExecutorServiceConfiguration.getScheduledThreadPoolExecutorCorePoolSize()), (Runnable r) -> { - Thread t = new Thread(r, "payara-executor-service-scheduled-task"); - t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread thread, Throwable thrwbl) { - Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Uncaught exception in Payara Scheduled Executor thread ",thrwbl); - } - }); - return t; - }); - scheduledThreadPoolExecutor.setRemoveOnCancelPolicy(true); + } public Future submit(Callable task) { @@ -322,4 +356,8 @@ private boolean isCurrentInstanceMatchTarget(PropertyChangeEvent pe) { return false; } + + public boolean isACC() { + return processEnvironment.getProcessType().equals(ACC); + } }