Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-10.0.x

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2020-09-02 23:47:10 +02:00
commit 1c3b816031
5 changed files with 168 additions and 54 deletions

View File

@ -1,19 +1,19 @@
// //
// ======================================================================== // ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
// ========================================================================
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// //
// This program and the accompanying materials are made available under // The Eclipse Public License is available at
// the terms of the Eclipse Public License 2.0 which is available at // http://www.eclipse.org/legal/epl-v10.html
// https://www.eclipse.org/legal/epl-2.0
// //
// This Source Code may also be made available under the following // The Apache License v2.0 is available at
// Secondary Licenses when the conditions for such availability set // http://www.opensource.org/licenses/apache2.0.php
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
// //
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 // You may elect to redistribute this code under either of these licenses.
// ======================================================================== // ========================================================================
// //
[[start-jar]] [[start-jar]]
@ -65,7 +65,7 @@ When executed `start.jar` performs the following actions:
3. Uses default behavior of `java.io.File` (Relative to `System.getProperty` ("user.dir") and then as absolute file system path). 3. Uses default behavior of `java.io.File` (Relative to `System.getProperty` ("user.dir") and then as absolute file system path).
* Loads any dependent modules (merges XXNK, library, and properties results with active command line). * Loads any dependent modules (merges XXNK, library, and properties results with active command line).
* Builds out server classpath. * Builds out server classpath.
* Determines run mode: * Determines run mode as one of:
** Shows informational command line options and exit. ** Shows informational command line options and exit.
** Executes Jetty normally, waits for Jetty to stop. ** Executes Jetty normally, waits for Jetty to stop.
** Executes a forked JVM to run Jetty in, waits for forked JVM to exit. ** Executes a forked JVM to run Jetty in, waits for forked JVM to exit.
@ -89,9 +89,36 @@ Lists the resolved configuration that will start Jetty.
* Server classpath * Server classpath
* Server XML configuration files * Server XML configuration files
--dry-run:: --dry-run::
Prints the resolved command line that `start.jar` should use to start a forked instance of Jetty. Print the command line that the start.jar generates, then exit. This may be used to generate command lines when the start.ini includes -X or -D arguments:
....
$ java -jar start.jar --dry-run > jetty.sh
$ . jetty.sh
....
--dry-run=<parts>::
Print specific parts of the command line. The parts are a comma separated list of:
* "java" - the JVM to run
* "opts" - the JVM options (eg -D and -X flags)
* "path" - the JVM class path or JPMS modules options
* "main" - the main class to run
* "args" - the arguments passed to the main class
It is possible to decompose the start command:
....
$ OPTS=$(java -jar start.jar --dry-run=opts,path)
$ MAIN=$(java -jar start.jar --dry-run=main)
$ ARGS=$(java -jar start.jar --dry-run=args)
$ java $OPTS -Dextra=opt $MAIN $ARGS extra=arg
....
Alternatively to create an args file for java:
....
$ java -jar start.jar --dry-run=opts,path,main,args > /tmp/args
$ java @/tmp/args
....
--exec:: --exec::
Starts a forked instance of Jetty. Forces the start to use a forked instance of java to run Jetty.
Some modules include `--exec` in order to set java command line options.
Some start options, such as `--jpms` also imply `--exec`
--exec-properties=<filename>:: --exec-properties=<filename>::
Assign a fixed name to the file used to transfer properties to the sub process. Assign a fixed name to the file used to transfer properties to the sub process.
This allows the generated properties file to be saved and reused. This allows the generated properties file to be saved and reused.
@ -99,7 +126,7 @@ Without this option, a temporary file is used.
--commands=<filename>:: --commands=<filename>::
Instructs `start.jar` to use each line of the specified file as arguments on the command line. Instructs `start.jar` to use each line of the specified file as arguments on the command line.
===== Debugg and Start Logging ===== Debug and Start Logging
--debug:: --debug::
Enables debugging output of the startup procedure. Enables debugging output of the startup procedure.
@ -275,3 +302,25 @@ If you have a need for a shaded version of `start.jar` (such as for Gradle), you
<classifier>shaded</classifier> <classifier>shaded</classifier>
</dependency> </dependency>
.... ....
==== Start.jar without exec or forking.
Some Jetty modules include the `--exec` option so that java command line options can be set.
Also some `start.jar` options (eg. `--jpms`) include an implicit `--exec`.
To start jetty without forking a new JVM instance from the start JVM, the `--dry-run` option can be used to generate a command line:
....
$ CMD=$(java -jar start.jar --dry-run)
$ $CMD
....
It is possible to decompose the start command so that it can be modified:
....
$ OPTS=$(java -jar start.jar --dry-run=opts,path)
$ MAIN=$(java -jar start.jar --dry-run=main)
$ ARGS=$(java -jar start.jar --dry-run=args)
$ java $OPTS -Dextra=opt $MAIN $ARGS extra=arg
....
Alternatively to create an args file for java:
....
$ java -jar start.jar --dry-run=opts,path,main,args > /tmp/args
$ java @/tmp/args
....

View File

@ -206,7 +206,7 @@ public class Main
StartLog.debug("%s - %s", invokedClass, invokedClass.getPackage().getImplementationVersion()); StartLog.debug("%s - %s", invokedClass, invokedClass.getPackage().getImplementationVersion());
CommandLineBuilder cmd = args.getMainArgs(false); CommandLineBuilder cmd = args.getMainArgs(StartArgs.ARG_PARTS);
String[] argArray = cmd.getArgs().toArray(new String[0]); String[] argArray = cmd.getArgs().toArray(new String[0]);
StartLog.debug("Command Line Args: %s", cmd.toString()); StartLog.debug("Command Line Args: %s", cmd.toString());
@ -407,7 +407,7 @@ public class Main
// Show Command Line to execute Jetty // Show Command Line to execute Jetty
if (args.isDryRun()) if (args.isDryRun())
{ {
CommandLineBuilder cmd = args.getMainArgs(true); CommandLineBuilder cmd = args.getMainArgs(args.getDryRunParts());
System.out.println(cmd.toString(StartLog.isDebugEnabled() ? " \\\n" : " ")); System.out.println(cmd.toString(StartLog.isDebugEnabled() ? " \\\n" : " "));
} }
@ -446,7 +446,7 @@ public class Main
// execute Jetty in another JVM // execute Jetty in another JVM
if (args.isExec()) if (args.isExec())
{ {
CommandLineBuilder cmd = args.getMainArgs(true); CommandLineBuilder cmd = args.getMainArgs(StartArgs.ALL_PARTS);
cmd.debug(); cmd.debug();
ProcessBuilder pbuilder = new ProcessBuilder(cmd.getArgs()); ProcessBuilder pbuilder = new ProcessBuilder(cmd.getArgs());
StartLog.endStartLog(); StartLog.endStartLog();

View File

@ -57,6 +57,14 @@ import org.eclipse.jetty.util.ManifestUtils;
public class StartArgs public class StartArgs
{ {
public static final String VERSION; public static final String VERSION;
public static final Set<String> ALL_PARTS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
"java",
"opts",
"path",
"main",
"args")));
public static final Set<String> ARG_PARTS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
"args")));
static static
{ {
@ -219,6 +227,7 @@ public class StartArgs
private boolean listConfig = false; private boolean listConfig = false;
private boolean version = false; private boolean version = false;
private boolean dryRun = false; private boolean dryRun = false;
private final Set<String> dryRunParts = new HashSet<>();
private boolean jpms = false; private boolean jpms = false;
private boolean createStartd = false; private boolean createStartd = false;
private boolean updateIni = false; private boolean updateIni = false;
@ -676,8 +685,11 @@ public class StartArgs
return jvmArgs; return jvmArgs;
} }
public CommandLineBuilder getMainArgs(boolean addJavaInit) throws IOException public CommandLineBuilder getMainArgs(Set<String> parts) throws IOException
{ {
if (parts.isEmpty())
parts = ALL_PARTS;
CommandLineBuilder cmd = new CommandLineBuilder(); CommandLineBuilder cmd = new CommandLineBuilder();
// Special Stop/Shutdown properties // Special Stop/Shutdown properties
@ -685,10 +697,11 @@ public class StartArgs
ensureSystemPropertySet("STOP.KEY"); ensureSystemPropertySet("STOP.KEY");
ensureSystemPropertySet("STOP.WAIT"); ensureSystemPropertySet("STOP.WAIT");
if (addJavaInit) if (parts.contains("java"))
{
cmd.addRawArg(CommandLineBuilder.findJavaBin()); cmd.addRawArg(CommandLineBuilder.findJavaBin());
if (parts.contains("opts"))
{
cmd.addRawArg("-Djava.io.tmpdir=" + System.getProperty("java.io.tmpdir")); cmd.addRawArg("-Djava.io.tmpdir=" + System.getProperty("java.io.tmpdir"));
cmd.addRawArg("-Djetty.home=" + baseHome.getHome()); cmd.addRawArg("-Djetty.home=" + baseHome.getHome());
cmd.addRawArg("-Djetty.base=" + baseHome.getBase()); cmd.addRawArg("-Djetty.base=" + baseHome.getBase());
@ -703,6 +716,7 @@ public class StartArgs
Prop p = processSystemProperty(key, value, null); Prop p = processSystemProperty(key, value, null);
cmd.addRawArg("-D" + p.key + "=" + getProperties().expand(p.value)); cmd.addRawArg("-D" + p.key + "=" + getProperties().expand(p.value));
} }
else else
{ {
@ -716,7 +730,10 @@ public class StartArgs
String value = System.getProperty(propKey); String value = System.getProperty(propKey);
cmd.addEqualsArg("-D" + propKey, value); cmd.addEqualsArg("-D" + propKey, value);
} }
}
if (parts.contains("path"))
{
if (isJPMS()) if (isJPMS())
{ {
Map<Boolean, List<File>> dirsAndFiles = StreamSupport.stream(classpath.spliterator(), false) Map<Boolean, List<File>> dirsAndFiles = StreamSupport.stream(classpath.spliterator(), false)
@ -765,52 +782,58 @@ public class StartArgs
cmd.addRawArg("--add-reads"); cmd.addRawArg("--add-reads");
cmd.addRawArg(entry.getKey() + "=" + String.join(",", entry.getValue())); cmd.addRawArg(entry.getKey() + "=" + String.join(",", entry.getValue()));
} }
cmd.addRawArg("--module");
cmd.addRawArg(getMainClassname());
} }
else else
{ {
cmd.addRawArg("-cp"); cmd.addRawArg("-cp");
cmd.addRawArg(classpath.toString()); cmd.addRawArg(classpath.toString());
cmd.addRawArg(getMainClassname());
} }
} }
if (parts.contains("main"))
{
if (isJPMS())
cmd.addRawArg("--module");
cmd.addRawArg(getMainClassname());
}
// pass properties as args or as a file // pass properties as args or as a file
if (dryRun && execProperties == null) if (parts.contains("args"))
{ {
for (Prop p : properties) if (dryRun && execProperties == null)
{ {
cmd.addRawArg(CommandLineBuilder.quote(p.key) + "=" + CommandLineBuilder.quote(p.value)); for (Prop p : properties)
{
cmd.addRawArg(CommandLineBuilder.quote(p.key) + "=" + CommandLineBuilder.quote(p.value));
}
} }
} else if (properties.size() > 0)
else if (properties.size() > 0)
{
Path propPath;
if (execProperties == null)
{ {
propPath = Files.createTempFile("start_", ".properties"); Path propPath;
propPath.toFile().deleteOnExit(); if (execProperties == null)
} {
else propPath = Files.createTempFile("start_", ".properties");
propPath = new File(execProperties).toPath(); propPath.toFile().deleteOnExit();
}
else
propPath = new File(execProperties).toPath();
try (OutputStream out = Files.newOutputStream(propPath)) try (OutputStream out = Files.newOutputStream(propPath))
{
properties.store(out, "start.jar properties");
}
cmd.addRawArg(propPath.toAbsolutePath().toString());
}
for (Path xml : xmls)
{ {
properties.store(out, "start.jar properties"); cmd.addRawArg(xml.toAbsolutePath().toString());
} }
cmd.addRawArg(propPath.toAbsolutePath().toString());
}
for (Path xml : xmls) for (Path propertyFile : propertyFiles)
{ {
cmd.addRawArg(xml.toAbsolutePath().toString()); cmd.addRawArg(propertyFile.toAbsolutePath().toString());
} }
for (Path propertyFile : propertyFiles)
{
cmd.addRawArg(propertyFile.toAbsolutePath().toString());
} }
return cmd; return cmd;
@ -936,6 +959,11 @@ public class StartArgs
return dryRun; return dryRun;
} }
public Set<String> getDryRunParts()
{
return dryRunParts;
}
public boolean isExec() public boolean isExec()
{ {
return exec; return exec;
@ -1154,6 +1182,21 @@ public class StartArgs
return; return;
} }
if (arg.startsWith("--dry-run="))
{
int colon = arg.indexOf('=');
for (String part : arg.substring(colon + 1).split(","))
{
if (!ALL_PARTS.contains(part))
throw new UsageException(UsageException.ERR_BAD_ARG, "Unrecognized --dry-run=\"%s\" in %s", part, source);
dryRunParts.add(part);
}
dryRun = true;
run = false;
return;
}
// Enable forked execution of Jetty server // Enable forked execution of Jetty server
if ("--exec".equals(arg)) if ("--exec".equals(arg))
{ {

View File

@ -28,7 +28,30 @@ Command Line Options:
--dry-run Print the command line that the start.jar generates, --dry-run Print the command line that the start.jar generates,
then exit. This may be used to generate command lines then exit. This may be used to generate command lines
when the start.ini includes -X or -D arguments. when the start.ini includes -X or -D arguments:
java -jar start.jar --dry-run > jetty.sh
. jetty.sh
--dry-run=parts Print specific parts of the command line. The parts
are a comma separated list of
o "java" - the JVM to run
o "opts" - the JVM options (eg -D and -X flags)
o "path" - the JVM class path or JPMS modules options
o "main" - the main class to run
o "args" - the arguments passed to the main class
It is possible to decompose the start command:
OPTS=$(java -jar start.jar --dry-run=opts,path)
MAIN=$(java -jar start.jar --dry-run=main)
ARGS=$(java -jar start.jar --dry-run=args)
java $OPTS -Dextra=opt $MAIN $ARGS extra=arg
Alternatively to create an args file for java:
java -jar start.jar --dry-run=opts,path,main,args > /tmp/args
java @/tmp/args
--exec Run the generated command line (see --dry-run) in --exec Run the generated command line (see --dry-run) in
a sub process. This can be used when start.ini a sub process. This can be used when start.ini
@ -59,7 +82,6 @@ Debug and Start Logging:
issues where the jetty specific logger has not yet kicked issues where the jetty specific logger has not yet kicked
in due to startup configuration errors. in due to startup configuration errors.
Module Management: Module Management:
------------------ ------------------

View File

@ -193,7 +193,7 @@ public class MainTest
assertThat("jetty.home", baseHome.getHome(), is(homePath.toString())); assertThat("jetty.home", baseHome.getHome(), is(homePath.toString()));
assertThat("jetty.base", baseHome.getBase(), is(homePath.toString())); assertThat("jetty.base", baseHome.getBase(), is(homePath.toString()));
CommandLineBuilder commandLineBuilder = args.getMainArgs(true); CommandLineBuilder commandLineBuilder = args.getMainArgs(StartArgs.ALL_PARTS);
String commandLine = commandLineBuilder.toString("\n"); String commandLine = commandLineBuilder.toString("\n");
String expectedExpansion = String.format("-Xloggc:%s/logs/gc-%s.log", String expectedExpansion = String.format("-Xloggc:%s/logs/gc-%s.log",
baseHome.getBase(), System.getProperty("java.version") baseHome.getBase(), System.getProperty("java.version")