All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.appclient.client.CLIBootstrap Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright (c) 2010-2017 Oracle 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
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 * 
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 * 
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 * 
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
// Portions Copyright 2018-2022 Payara Foundation and/or affiliates

package org.glassfish.appclient.client;

import com.sun.enterprise.util.LocalStringManager;
import com.sun.enterprise.util.LocalStringManagerImpl;
import com.sun.enterprise.util.OS;
import org.glassfish.appclient.client.acc.UserError;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import static java.util.Objects.nonNull;
import static java.util.stream.Collectors.joining;

/**
 *
 * 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 * directories are included * 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: * *

 * {@code
 * java \
 *   (user-specified JVM options except -jar) \
 *   -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). * * @author Tim Quinn */ public class CLIBootstrap { public final static String FILE_OPTIONS_INTRODUCER = "argsfile="; private final static String COMMA_IN_ARG_PLACEHOLDER = "+-+-+-+"; private final static boolean isDebug = System.getenv("AS_DEBUG") != null; private final static String INPUT_ARGS = System.getenv("inputArgs"); 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"; /** options to the ACC that take no value */ 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[] ENV_VARS = { "_AS_INSTALL", "APPCPATH", "VMARGS" }; 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 accValuedOptions, accUnvaluedOptions, jvmPropertySettings, jvmValuedOptions, otherJVMOptions, arguments; /** arguments passed to the ACC Java agent */ private final AgentArgs agentArgs = new AgentArgs(); /** records how the user specifies the main class: -jar xxx.jar, -client xxx.jar, or a.b.MainClass */ private final JVMMainOption jvmMainSetting = new JVMMainOption(); /** 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 */ private CommandLineElement[] elementsInOutputOrder; /** * @param args the command line arguments */ public static void main(String[] args) { try { //Convert env vars to properties. (This makes testing easier.) envToProps(); // 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); } 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. // System.out.print(outputCommandLine); } catch (Exception ex) { ex.printStackTrace(); System.exit(1); } catch (UserError ue) { ue.displayAndExit(); } } /** * 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 input string to encode * @return encoded string */ public static String encodeArg(String input) { return input.replace(",", COMMA_IN_ARG_PLACEHOLDER); } /** * Replaces occurrences of comma encoding with commas. * * @param input possibly encoded string * @return decoded string */ public static String decodeArg(String input) { return input.replace(COMMA_IN_ARG_PLACEHOLDER, ","); } 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). */ Pattern argPattern = Pattern.compile("\"([^\"]+)\"|([^\"\\s]+)"); 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); if (isDebug) { System.err.println("Captured argument " + arg); } } return argList.toArray(new String[argList.size()]); } private static void envToProps() { for (String envVar : ENV_VARS) { String value = System.getenv(envVar); if (value != null) { System.setProperty(ENV_VAR_PROP_PREFIX + envVar, value); if (isDebug) { System.err.println(ENV_VAR_PROP_PREFIX + envVar + " set to " + value); } } } } CLIBootstrap() throws UserError { 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. */ 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); 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. */ 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. */ elementsInScanOrder = new CommandLineElement[]{ accValuedOptions, accUnvaluedOptions, jvmValuedOptions, jvmPropertySettings, jvmMainSetting, otherJVMOptions, arguments}; /* * Add the elements in this order so they appear in the generated java command in the correct positions. */ elementsInOutputOrder = new CommandLineElement[]{ jvmValuedOptions, jvmPropertySettings, otherJVMOptions, accUnvaluedOptions, accValuedOptions, jvmMainSetting, arguments }; } /** * 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(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. * * @param s * @return */ private static String quoteSuppressTokenSubst(final String s) { return OS.isWindows() ? quote(s) : quote(s.replace("$", "\\$")); } /** * Manages the arguments which will be passed to the ACC Java agent. */ private static class AgentArgs { private final StringBuilder args = new StringBuilder("=mode=acscript"); private char sep = ','; AgentArgs() { String appcPath = System.getProperty(ENV_VAR_PROP_PREFIX + "APPCPATH"); if (appcPath != null && appcPath.length() > 0) { add("appcpath=" + quote(appcPath)); } } /** * 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() { return args.toString(); } } /** * A command-line element. Various subtypes have some different behavior for some of the methods. */ private class CommandLineElement { private final Pattern pattern; private final Pattern whiteSpacePattern = Pattern.compile("[\\r\\n]"); /** allows multiple values; not all command line elements support this */ final List values = new ArrayList(); CommandLineElement(String patternString) { this(patternString, 0); } CommandLineElement(String patternString, int flags) { pattern = Pattern.compile(patternString, flags); } 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) */ int processValue(String[] args, int slot) throws UserError { // 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. * * @param element */ void addToAgentArgs(final String element) { } /** * Returns whether there is a next argument. * * @param args * @param currentSlot * @return */ boolean isNextArg(String[] args, int currentSlot) { return currentSlot < args.length - 1; } /** * 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) { 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. * * @param args * @param currentSlot * @throws UserError */ void ensureNonOptionNextArg(final String[] args, final int currentSlot) throws UserError { if ((currentSlot >= args.length - 1) || (args[currentSlot + 1].charAt(0) == '-')) { throw new UserError("Command line element " + args[currentSlot] + " requires non-option value"); } } /** * 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 */ 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. * * @param commandLine * @param useQuotes * @return true if any values from this command-line element were added to the command line; false otherwise */ boolean format(StringBuilder commandLine, boolean useQuotes) { boolean needSep = false; for (String value : values) { if (needSep) { commandLine.append(valueSep()); } format(commandLine, useQuotes, value); needSep = true; } 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. * * @return */ char valueSep() { return ' '; } /** * 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(StringBuilder commandLine, boolean useQuotes, String v) { if (commandLine.length() > 0) { commandLine.append(' '); } commandLine.append((useQuotes ? quoteSuppressTokenSubst(v) : v)); return commandLine; } } /** * A command-line option (an element which starts with "-"). */ private class Option extends CommandLineElement { Option(String patternString) { super(patternString); } } /** * 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. * */ private class JVMOption extends Option { JVMOption(String patternString, CommandLineElement vmargsJVMOptionElement) { super(patternString); if (vmargsJVMOptionElement != null) { values.addAll(vmargsJVMOptionElement.values); } } @Override boolean matches(String element) { /* * 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); } } /** * 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. */ private class ACCUnvaluedOption extends Option { ACCUnvaluedOption(final String patternString) { super(patternString); } @Override boolean matches(String element) { return (!jvmMainSetting.isJarSetting()) && super.matches(element); } @Override int processValue(String[] args, int slot) throws UserError { int result = super.processValue(args, slot); agentArgs.addACCArg(values.get(values.size() - 1)); return result; } @Override boolean format(StringBuilder commandLine) { /* * We do not send ACC arguments to the Java command line. They are placed into the agent argument string instead. */ return false; } } /** * An option that takes a value as the next command line element. */ private class ValuedOption extends Option { class OptionValue { private String option; private String value; OptionValue(final String option, final String value) { this.option = option; this.value = value; } } List optValues = new ArrayList(); ValuedOption(final String patternString) { super(patternString); } @Override int processValue(String[] args, int slot) throws UserError { ensureNonOptionNextArg(args, slot); optValues.add(new OptionValue(args[slot++], args[slot++])); 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(); } } private class JVMValuedOption extends ValuedOption { JVMValuedOption(final String patternString, final CommandLineElement vmargsJVMValuedOption) { super(patternString); if (vmargsJVMValuedOption != null) { values.addAll(vmargsJVMValuedOption.values); } } @Override boolean matches(final String element) { return (!jvmMainSetting.isJarSetting()) && super.matches(element); } @Override int processValue(String[] args, int slot) throws UserError { ensureNonOptionNextArg(args, slot); String key = args[slot++]; String value = args[slot++]; if(key.equals("-cp")) { value = Stream.of(value.split(";")) .map(cp -> quote(cp)) .collect(joining(";")); } optValues.add(new OptionValue(key, value)); return slot; } } /** * ACC options can appear until "-jar xxx" on the command line. */ private class ACCValuedOption extends ValuedOption { ACCValuedOption(final String patternString) { super(patternString); } @Override boolean matches(final String element) { return (!jvmMainSetting.isJarSetting()) && super.matches(element); } @Override int processValue(String[] args, int slot) throws UserError { 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. */ 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. */ private class JVMMainOption extends CommandLineElement { private static final String JVM_MAIN_PATTERN = "-jar|-client|[^-][^\\s]*"; private String introducer = null; private String mainClass = null; JVMMainOption() { super(JVM_MAIN_PATTERN); } boolean isJarSetting() { return "-jar".equals(introducer); } boolean isClientSetting() { return "-client".equals(introducer); } boolean isClassSetting() { return mainClass != null; } boolean isSet() { return !values.isEmpty(); } @Override int processValue(String[] args, int slot) throws UserError { /* * We only care about the most recent setting. */ 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 (args[slot].charAt(0) == '-') { if (nextLooksOK(args, slot)) { introducer = args[slot++]; final int result = super.processValue(args, slot); final String path = values.get(values.size() - 1); 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. */ agentArgs.add("client=dir=" + quote(clientSpec.getAbsolutePath())); introducer = "-jar"; values.set(values.size() - 1, gfInfo.agentJarPath()); } 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. */ if (path.endsWith(".ear")) { introducer = "-jar"; values.set(values.size() - 1, gfInfo.agentJarPath()); } } return result; } else { throw new UserError("-jar or -client requires value but missing"); } } else { /* * This must be a main class specified on the command line. */ final int result = super.processValue(args, slot); agentArgs.add("client=class=" + values.get(values.size() - 1)); mainClass = values.get(values.size() - 1); return result; } } @Override boolean format(final StringBuilder commandLine) { if(nonNull(mainClass)) { super.format(commandLine, false /* useQuotes */, mainClass); return true; } else 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. */ super.format(commandLine, false /* useQuotes */, "-jar"); return super.format(commandLine, true /* useQuotes */); } return super.format(commandLine, false /* useQuotes */); } private boolean nextLooksOK(final String[] args, final int slot) { return (isNextArg(args, slot) && (args[slot + 1].charAt(0) != '-')); } } /** * 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 = new JavaInfo(); gfInfo = new GlassFishInfo(); 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;) { boolean isMatched = false; for (CommandLineElement commandLineElement : elementsInScanOrder) { if (isMatched = commandLineElement.matches(augmentedArgs[i])) { i = commandLineElement.processValue(augmentedArgs, i); break; } } if (!isMatched) { throw new UserError("arg " + i + " = " + augmentedArgs[i] + " not recognized"); } } 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.) */ 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); } boolean needSep = true; for (CommandLineElement commandLineElement : elementsInOutputOrder) { needSep = processCommandElement(command, commandLineElement, needSep); } return command.toString(); } /** * 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"); } 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); } /** * 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 { return '=' + FILE_OPTIONS_INTRODUCER + quote(fileContainingAgentArgs().getAbsolutePath()); } catch (Exception ex) { throw new RuntimeException(ex); } } private File fileContainingAgentArgs() throws IOException { 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. *

* 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; GlassFishInfo() { String asInstallPath = System.getProperty(ENV_VAR_PROP_PREFIX + "_AS_INSTALL"); if (asInstallPath == null || asInstallPath.length() == 0) { throw new IllegalArgumentException("_AS_INSTALL == null"); } home = new File(asInstallPath); modules = new File(home, "modules"); lib = new File(home, "lib"); libAppclient = new File(lib, "appclient"); } File home() { return home; } File modules() { return modules; } File lib() { return 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. File configXMLFile = new File(new File(home, ACC_CONFIG_PREFIX), "glassfish-acc.xml"); if (configXMLFile.canRead()) { return configXMLFile; } 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. return configXMLFile; } String agentJarPath() { return new File(lib, "gf-client.jar").getAbsolutePath(); } File securityPolicy() { return new File(libAppclient, "client.policy"); } File loginConfig() { return new File(libAppclient, "appclientlogin.conf"); } } /** * 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). */ static class JavaInfo { 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. */ 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; JavaInfo() { jreHome = new File(System.getProperty("java.home")); javaExe = javaExe(); } protected boolean isValid() { return javaExe != null && new File(javaExe).canExecute(); } protected File javaBinDir() { return new File(jreHome, "bin"); } String javaExe() { return System.getenv(ACCJava_ENV_VAR_NAME); } File lib() { return new File(jreHome, "lib"); } String pathSeparator() { return useWindowsSyntax ? ";" : ":"; } } /** * 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. *

* 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 evJVMPropertySettings; private CommandLineElement evJVMValuedOptions; private CommandLineElement evOtherJVMOptions; private final List evElements = new ArrayList(); UserVMArgs(final String vmargs) throws UserError { if (isDebug) { System.err.println("VMARGS = " + (vmargs == null ? "null" : vmargs)); } evJVMPropertySettings = new JVMOption("-D.*", null); evJVMValuedOptions = new JVMValuedOption(JVM_VALUED_OPTIONS_PATTERN, null); evOtherJVMOptions = new JVMOption("-.*", null); initEVCommandLineElements(); if (vmargs == null) { return; } processEVCommandLineElements(convertInputArgsVariable(vmargs)); } private void initEVCommandLineElements() { evElements.add(evJVMPropertySettings); evElements.add(evJVMValuedOptions); evElements.add(evOtherJVMOptions); } private void processEVCommandLineElements(final String[] envVarJVMArgs) throws UserError { /* * Process each command-line argument by the first CommandLineElement which matches the argument. */ for (int i = 0; i < envVarJVMArgs.length;) { boolean isMatched = false; for (CommandLineElement commandLineElement : evElements) { if (isMatched = commandLineElement.matches(envVarJVMArgs[i])) { i = commandLineElement.processValue(envVarJVMArgs, i); break; } } if (!isMatched) { throw new UserError("arg " + i + " = " + envVarJVMArgs[i] + " not recognized"); } } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy