Issue #4562 remove deprecated jetty-runner (#4563)

Signed-off-by: olivier lamy <oliver.lamy@gmail.com>
This commit is contained in:
Olivier Lamy 2020-02-13 11:13:20 +10:00 committed by GitHub
parent 3c9c506644
commit ebed3e5b38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 0 additions and 1235 deletions

View File

@ -74,5 +74,4 @@ include::jndi/chapter.adoc[]
include::alpn/chapter.adoc[]
include::fastcgi/chapter.adoc[]
include::extras/chapter.adoc[]
include::runner/chapter.adoc[]
include::tuning/chapter.adoc[]

View File

@ -1,24 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// 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
// ========================================================================
//
[[runner]]
== Jetty Runner
This chapter explains how to use the `jetty-runner` to run your webapps without needing an installation of Jetty.
include::jetty-runner.adoc[]

View File

@ -1,349 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// 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
// ========================================================================
//
[[jetty-runner]]
=== Use Jetty Without an Installed Distribution
The idea of the `jetty-runner` is extremely simple run a webapp directly from the command line using a single jar file and as much default configuration as possible.
Of course, if your webapp is not as straightforward, the `jetty-runner` has command line options which allow you to customize the execution environment.
[[jetty-runner-preparation]]
==== Preparation
You will need the `jetty-runner` jar:
1. Download the `jetty-runner` jar available at https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-runner/[Maven Central].
==== Deploying a Simple Context
Let's assume we have a very simple webapp that does not need any resources from its environment, nor any configuration apart from the defaults.
Starting it is as simple as performing the following:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar simple.war
....
This will start Jetty on port 8080, and deploy the webapp to `/`.
Your webapp does not have to be packed into a war, you can deploy a webapp that is a directory instead in the same way:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar simple
....
In fact, the webapp does not have to be a war or even a directory, it can simply be a Jetty link:#using-context-provider[context xml] file that describes your webapp:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar simple-context.xml
....
____
[NOTE]
When using a context xml file, the application being deployed is not even required to be a fully-fledged webapp.
It can simply be a Jetty link:#what-is-a-context[context].
____
By default, `jetty-runner` implements all Configuration Classes so that users can set up and deploy new instances with as little configuration as possible.
If you wish to only implement certain Configuration Classes, they will need to be defined in the context xml for the webapp/context.
The default Configuration Classes are:
`org.eclipse.jetty.webapp.WebInfConfiguration`
`org.eclipse.jetty.webapp.WebXmlConfiguration`
`org.eclipse.jetty.webapp.MetaInfConfiguration`
`org.eclipse.jetty.webapp.FragmentConfiguration`
`org.eclipse.jetty.webapp.JettyWebXmlConfiguration`
`org.eclipse.jetty.plus.webapp.EnvConfiguration`
`org.eclipse.jetty.plus.webapp.PlusConfiguration`
`org.eclipse.jetty.annotations.AnnotationConfiguration`
You can learn more about implementing specific Configuration Classes link:https://www.eclipse.org/jetty/documentation/current/configuring-webapps.html#webapp-configurations[here.]
==== Deploying Multiple Contexts
If you have more than one webapp that must be deployed, simply provide them all on the command line.
You can control the context paths for them using the `--path` parameter.
Here's an example of deploying 2 wars (although either or both of them could be unpacked directories instead):
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --path /one my1.war --path /two my2.war
....
If you have context xml files that describe your webapps, you can fully configure your webapps in them and hence you won't need to use the command line switches.
Just provide the list of context files like so:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar my-first-context.xml my-second-context.xml my-third-context.xml
....
____
[NOTE]
Switched used on the command line override configuration file settings.
So, for example, you could set the context path for the webapp inside the context xml file, and use the `--path` switch to override it on the command line.
____
===== Changing the Default Port
By default the `jetty-runner` will listen on port 8080.
You can easily change this on the command line using the `--port` command.
Here's an example that runs our simple.war on port 9090:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --port 9090 simple.war
....
===== Using jetty.xml Files
Instead of, or in addition to, using command line switches, you can use one or more `jetty.xml` files to configure the environment for your webapps.
Here's an example where we apply two different `jetty.xml` files:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --config jetty.xml --config jetty-https.xml simple.war
....
[[runner-configuration-reference]]
==== Full Configuration Reference
You can see the fill set of configuration options using the `--help` switch:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --help
....
Here's what the output will look like:
[source, plain, subs="{sub-order}"]
----
Usage: java [-Djetty.home=dir] -jar jetty-runner.jar [--help|--version] [ server opts] [[ context opts] context ...]
Server opts:
--version - display version and exit
--log file - request log filename (with optional 'yyyy_mm_dd' wildcard
--out file - info/warn/debug log filename (with optional 'yyyy_mm_dd' wildcard
--host name|ip - interface to listen on (default is all interfaces)
--port n - port to listen on (default 8080)
--stop-port n - port to listen for stop command (or -DSTOP.PORT=n)
--stop-key n - security string for stop command (required if --stop-port is present) (or -DSTOP.KEY=n)
[--jar file]*n - each tuple specifies an extra jar to be added to the classloader
[--lib dir]*n - each tuple specifies an extra directory of jars to be added to the classloader
[--classes dir]*n - each tuple specifies an extra directory of classes to be added to the classloader
--stats [unsecure|realm.properties] - enable stats gathering servlet context
[--config file]*n - each tuple specifies the name of a jetty xml config file to apply (in the order defined)
Context opts:
[[--path /path] context]*n - WAR file, web app dir or context xml file, optionally with a context path
----
===== Printing the Version
Print out the version of Jetty and then exit immediately.
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --version
....
===== Configuring a Request Log
Cause Jetty to write a request log with the given name.
If the file is prefixed with `yyyy_mm_dd` then the file will be automatically rolled over.
Note that for finer grained configuration of the link:{JDURL}/org/eclipse/jetty/server/NCSARequestLog.html[request log], you will need to use a Jetty xml file instead.
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --log yyyy_mm_dd-requests.log my.war
....
===== Configuring the Output Log
Redirect the output of jetty logging to the named file.
If the file is prefixed with `yyyy_mm_dd` then the file will be automatically rolled over.
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --out yyyy_mm_dd-output.log my.war
....
===== Configuring the Interface for HTTP
Like Jetty standalone, the default is for the connectors to listen on all interfaces on a machine.
You can control that by specifying the name or ip address of the particular interface you wish to use with the `--host` argument:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --host 192.168.22.19 my.war
....
===== Configuring the Port for HTTP
The default port number is 8080.
To link:#how-to-configure-connectors[configure a https connector], use a Jetty xml config file instead.
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --port 9090 my.war
....
===== Configuring Stop
You can configure a port number for Jetty to listen on for a stop command, so you are able to stop it from a different terminal.
This requires the use of a "secret" key, to prevent malicious or accidental termination.
Use the `--stop-port` and `--stop-key` (or `-DSTOP.PORT=` and `-DSTOP.KEY=`, respectively) parameters as arguments to the `jetty-runner`:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --stop-port 8181 --stop-key abc123
....
Then, to stop Jetty from a different terminal, you need to supply the same port and key information.
For this you'll either need a local installation of Jetty, the link:#jetty-maven-plugin[jetty-maven-plugin], the link:#jetty-ant[jetty-ant plugin], or a custom class.
Here's how to use a Jetty installation to perform a stop:
[source, screen, subs="{sub-order}"]
....
> java -jar start.jar -DSTOP.PORT=8181 -DSTOP.KEY=abc123 --stop
....
===== Configuring the Container Classpath
With a local installation of Jetty, you add jars and classes to the container's classpath by putting them in the `{$jetty.base}/lib` directory.
With the `jetty-runner`, you can use the `--lib`, `--jar` and `--classes` arguments instead to achieve the same thing.
`--lib` adds the location of a directory which contains jars to add to the container classpath.
You can add 1 or more.
Here's an example of configuring 2 directories:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --lib /usr/local/external/lib --lib $HOME/external-other/lib my.war
....
`--jar` adds a single jar file to the container classpath.
You can add 1 or more.
Here's an example of configuring 3 extra jars:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --jar /opt/stuff/jars/jar1.jar --jar $HOME/jars/jar2.jar --jar /usr/local/proj/jars/jar3.jar my.war
....
`--classes` add the location of a directory containing classes to add to the container classpath.
You can add 1 or more.
Here's an example of configuring a single extra classes dir:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --classes /opt/stuff/classes my.war
....
____
[NOTE]
When using the `--jar` and/or `--lib` arguments, by default these will *not* be inspected for `META-INF` information such as `META-INF/resources`, `META-INF/web-fragment.xml`, or `META-INF/taglib.tld`.
If you require these jar files inspected you will need to define the link:https://www.eclipse.org/jetty/documentation/current/configuring-webapps.html#webapp-context-attributes[jar pattern in your context xml file].
Jetty-Runner automatically provides and appends a suitable pattern for jtsl taglibs (this pattern is different than the one in the standard Jetty distribution).
____
===== Gathering Statistics
If statistics gathering is enabled, then they are viewable by surfing to the context `/stats`.
You may optionally protect access to that context with a password.
Here's an example of enabling statistics, with no password protection:
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --stats unsecure my.war
....
If we wished to protect access to the `/stats` context, we would provide the location of a Jetty realm configuration file containing authentication and authorization information.
For example, we could use the following example realm file from the Jetty distribution:
[source, screen, subs="{sub-order}"]
....
jetty: MD5:164c88b302622e17050af52c89945d44,user
admin: CRYPT:adpexzg3FUZAk,server-administrator,content-administrator,admin
other: OBF:1xmk1w261u9r1w1c1xmq,user
plain: plain,user
user: password,user
# This entry is for digest auth. The credential is a MD5 hash of username:realmname:password
digest: MD5:6e120743ad67abfbc385bc2bb754e297,user
....
Assuming we've copied it into the local directory, we would apply it like so
[source, screen, subs="{sub-order}"]
....
> java -jar jetty-runner.jar --stats realm.properties my.war
....
After navigating to http://localhost:8080/ a few times, we can point to the stats servlet on http://localhost:8080/stats to see the output:
....
Statistics:
Statistics gathering started 1490627ms ago
Requests:
Total requests: 9
Active requests: 1
Max active requests: 1
Total requests time: 63
Mean request time: 7.875
Max request time: 26
Request time standard deviation: 8.349764752888037
Dispatches:
Total dispatched: 9
Active dispatched: 1
Max active dispatched: 1
Total dispatched time: 63
Mean dispatched time: 7.875
Max dispatched time: 26
Dispatched time standard deviation: 8.349764752888037
Total requests suspended: 0
Total requests expired: 0
Total requests resumed: 0
Responses:
1xx responses: 0
2xx responses: 7
3xx responses: 1
4xx responses: 0
5xx responses: 0
Bytes sent total: 1453
Connections:
org.eclipse.jetty.server.ServerConnector@203822411
Protocols:http/1.1
Statistics gathering started 1490606ms ago
Total connections: 7
Current connections open: 1
Max concurrent connections open: 2
Total connections duration: 72883
Mean connection duration: 12147.166666666666
Max connection duration: 65591
Connection duration standard deviation: 23912.40292977684
Total messages in: 7
Total messages out: 7
Memory:
Heap memory usage: 49194840 bytes
Non-heap memory usage: 12611696 bytes
....

View File

@ -1,135 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>10.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-runner</artifactId>
<name>Jetty :: Runner</name>
<properties>
<assembly-directory>target/distribution</assembly-directory>
<bundle-symbolic-name>${project.groupId}.runner</bundle-symbolic-name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includes>**</includes>
<excludes>**/MANIFEST.MF,META-INF/*.RSA,META-INF/*.DSA,META-INF/*.SF,module-info.class</excludes>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId>
<executions>
<execution>
<id>integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>install</goal>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<scriptVariables>
<maven.dependency.plugin.version>${maven.dependency.plugin.version}</maven.dependency.plugin.version>
</scriptVariables>
<goals>
<goal>clean</goal>
</goals>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.neo4j.build.plugins</groupId>
<artifactId>clirr-maven-plugin</artifactId>
<configuration>
<!-- Clirr fails with "org.apache.tools.ant.Task not found" on this project -->
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<!-- jetty-runner is not an OSGi component -->
<skip>true</skip>
<!-- there is no way to skip MANIFEST creation by the plugin so just configure dummy location -->
<manifestLocation>${project.build.directory}/NON_USED_MANIFEST</manifestLocation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>src/main/resources/MANIFEST.MF</manifestFile>
<manifest>
<mainClass>org.eclipse.jetty.runner.Runner</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jaas</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-jetty-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jndi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jsp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jstl</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<profiles>
<profile>
<id>it-repo</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>local.central</id>
<url>@localRepositoryUrl@</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>local.central</id>
<url>@localRepositoryUrl@</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
</settings>

View File

@ -1 +0,0 @@
invoker.goals = generate-resources

View File

@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.its</groupId>
<artifactId>jetty-runner-it-test</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-runner</artifactId>
<version>@project.version@</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>@maven.dependency.plugin.version@</version>
<executions>
<execution>
<id>copy-jetty-runner</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-runner</artifactId>
<version>@project.version@</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/</outputDirectory>
<destFileName>jetty-runner.jar</destFileName>
</artifactItem>
</artifactItems>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,10 +0,0 @@
import java.util.jar.*
File artifact = new File( basedir, "target/jetty-runner.jar" )
assert artifact.exists()
JarFile jar = new JarFile( artifact );
Attributes manifest = jar.getManifest().getMainAttributes();
assert manifest.getValue( new Attributes.Name( "Main-Class" ) ).equals( "org.eclipse.jetty.runner.Runner" )

View File

@ -1,595 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// 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
// ========================================================================
//
package org.eclipse.jetty.runner;
import java.io.IOException;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import org.eclipse.jetty.io.ConnectionStatistics;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.CustomRequestLog;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.ShutdownMonitor;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.StatisticsServlet;
import org.eclipse.jetty.util.RolloverFileOutputStream;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
/**
* Runner
* <p>
* Combine jetty classes into a single executable jar and run webapps based on the args to it.
*
* @deprecated No replacement provided or available. Migrate to jetty-home (and use {@code ${jetty.base}} directory).
*/
@Deprecated
public class Runner
{
private static final Logger LOG = Log.getLogger(Runner.class);
public static final String[] PLUS_CONFIGURATION_CLASSES =
{
org.eclipse.jetty.webapp.WebInfConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.WebXmlConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.MetaInfConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.FragmentConfiguration.class.getCanonicalName(),
org.eclipse.jetty.plus.webapp.EnvConfiguration.class.getCanonicalName(),
org.eclipse.jetty.plus.webapp.PlusConfiguration.class.getCanonicalName(),
org.eclipse.jetty.annotations.AnnotationConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.JettyWebXmlConfiguration.class.getCanonicalName()
};
public static final String CONTAINER_INCLUDE_JAR_PATTERN = ".*/jetty-runner-[^/]*\\.jar$";
public static final String DEFAULT_CONTEXT_PATH = "/";
public static final int DEFAULT_PORT = 8080;
protected Server _server;
protected URLClassLoader _classLoader;
protected Classpath _classpath = new Classpath();
protected ContextHandlerCollection _contexts;
protected String _logFile;
protected ArrayList<String> _configFiles;
protected boolean _enableStats = false;
protected String _statsPropFile;
/**
* Classpath
*/
public class Classpath
{
private List<URI> _classpath = new ArrayList<>();
public void addJars(Resource lib) throws IOException
{
if (lib == null || !lib.exists())
throw new IllegalStateException("No such lib: " + lib);
String[] list = lib.list();
if (list == null)
return;
for (String path : list)
{
if (".".equals(path) || "..".equals(path))
continue;
try (Resource item = lib.addPath(path))
{
if (item.isDirectory())
addJars(item);
else
{
String lowerCasePath = path.toLowerCase(Locale.ENGLISH);
if (lowerCasePath.endsWith(".jar") ||
lowerCasePath.endsWith(".zip"))
{
_classpath.add(item.getURI());
}
}
}
}
}
public void addPath(Resource path)
{
if (path == null || !path.exists())
throw new IllegalStateException("No such path: " + path);
_classpath.add(path.getURI());
}
public URI[] asArray()
{
return _classpath.toArray(new URI[0]);
}
}
public Runner()
{
}
/**
* Generate helpful usage message and exit
*
* @param error the error header
*/
public void usage(String error)
{
if (error != null)
System.err.println("ERROR: " + error);
System.err.println("Usage: java [-Djetty.home=dir] -jar jetty-runner.jar [--help|--version] [ server opts] [[ context opts] context ...] ");
System.err.println("Server opts:");
System.err.println(" --version - display version and exit");
System.err.println(" --log file - request log filename (with optional 'yyyy_mm_dd' wildcard");
System.err.println(" --out file - info/warn/debug log filename (with optional 'yyyy_mm_dd' wildcard");
System.err.println(" --host name|ip - interface to listen on (default is all interfaces)");
System.err.println(" --port n - port to listen on (default 8080)");
System.err.println(" --stop-port n - port to listen for stop command (or -DSTOP.PORT=n)");
System.err.println(" --stop-key n - security string for stop command (required if --stop-port is present) (or -DSTOP.KEY=n)");
System.err.println(" [--jar file]*n - each tuple specifies an extra jar to be added to the classloader");
System.err.println(" [--lib dir]*n - each tuple specifies an extra directory of jars to be added to the classloader");
System.err.println(" [--classes dir]*n - each tuple specifies an extra directory of classes to be added to the classloader");
System.err.println(" --stats [unsecure|realm.properties] - enable stats gathering servlet context");
System.err.println(" [--config file]*n - each tuple specifies the name of a jetty xml config file to apply (in the order defined)");
System.err.println("Context opts:");
System.err.println(" [[--path /path] context]*n - WAR file, web app dir or context xml file, optionally with a context path");
System.exit(1);
}
/**
* Generate version message and exit
*/
public void version()
{
System.err.println("org.eclipse.jetty.runner.Runner: " + Server.getVersion());
System.exit(1);
}
/**
* Configure a jetty instance and deploy the webapps presented as args
*
* @param args the command line arguments
* @throws Exception if unable to configure
*/
public void configure(String[] args) throws Exception
{
// handle classpath bits first so we can initialize the log mechanism.
for (int i = 0; i < args.length; i++)
{
if ("--lib".equals(args[i]))
{
try (Resource lib = Resource.newResource(args[++i]))
{
if (!lib.exists() || !lib.isDirectory())
usage("No such lib directory " + lib);
_classpath.addJars(lib);
}
}
else if ("--jar".equals(args[i]))
{
try (Resource jar = Resource.newResource(args[++i]))
{
if (!jar.exists() || jar.isDirectory())
usage("No such jar " + jar);
_classpath.addPath(jar);
}
}
else if ("--classes".equals(args[i]))
{
try (Resource classes = Resource.newResource(args[++i]))
{
if (!classes.exists() || !classes.isDirectory())
usage("No such classes directory " + classes);
_classpath.addPath(classes);
}
}
else if (args[i].startsWith("--"))
i++;
}
initClassLoader();
LOG.info("Runner");
LOG.debug("Runner classpath {}", _classpath);
String contextPath = DEFAULT_CONTEXT_PATH;
boolean contextPathSet = false;
int port = DEFAULT_PORT;
String host = null;
int stopPort = Integer.getInteger("STOP.PORT", 0);
String stopKey = System.getProperty("STOP.KEY", null);
boolean runnerServerInitialized = false;
for (int i = 0; i < args.length; i++)
{
switch (args[i])
{
case "--port":
port = Integer.parseInt(args[++i]);
break;
case "--host":
host = args[++i];
break;
case "--stop-port":
stopPort = Integer.parseInt(args[++i]);
break;
case "--stop-key":
stopKey = args[++i];
break;
case "--log":
_logFile = args[++i];
break;
case "--out":
String outFile = args[++i];
PrintStream out = new PrintStream(new RolloverFileOutputStream(outFile, true, -1));
LOG.info("Redirecting stderr/stdout to " + outFile);
System.setErr(out);
System.setOut(out);
break;
case "--path":
contextPath = args[++i];
contextPathSet = true;
break;
case "--config":
if (_configFiles == null)
_configFiles = new ArrayList<>();
_configFiles.add(args[++i]);
break;
case "--lib":
++i;//skip
break;
case "--jar":
++i; //skip
break;
case "--classes":
++i;//skip
break;
case "--stats":
_enableStats = true;
_statsPropFile = args[++i];
_statsPropFile = ("unsecure".equalsIgnoreCase(_statsPropFile) ? null : _statsPropFile);
break;
default:
// process system property type argument so users can use in second args part
if (args[i].startsWith("-D"))
{
String[] sysProps = args[i].substring(2).split("=", 2);
if ("STOP.KEY".equals(sysProps[0]))
{
stopKey = sysProps[1];
break;
}
else if ("STOP.PORT".equals(sysProps[0]))
{
stopPort = Integer.parseInt(sysProps[1]);
break;
}
}
// process contexts
if (!runnerServerInitialized) // log handlers not registered, server maybe not created, etc
{
if (_server == null) // server not initialized yet
{
// build the server
_server = new Server();
}
//apply jetty config files if there are any
if (_configFiles != null)
{
for (String cfg : _configFiles)
{
try (Resource resource = Resource.newResource(cfg))
{
XmlConfiguration xmlConfiguration = new XmlConfiguration(resource);
xmlConfiguration.configure(_server);
}
}
}
//check that everything got configured, and if not, make the handlers
HandlerCollection handlers = (HandlerCollection)_server.getChildHandlerByClass(HandlerCollection.class);
if (handlers == null)
{
handlers = new HandlerCollection();
_server.setHandler(handlers);
}
//check if contexts already configured
_contexts = (ContextHandlerCollection)handlers.getChildHandlerByClass(ContextHandlerCollection.class);
if (_contexts == null)
{
_contexts = new ContextHandlerCollection();
prependHandler(_contexts, handlers);
}
if (_enableStats)
{
//if no stats handler already configured
if (handlers.getChildHandlerByClass(StatisticsHandler.class) == null)
{
StatisticsHandler statsHandler = new StatisticsHandler();
Handler oldHandler = _server.getHandler();
statsHandler.setHandler(oldHandler);
_server.setHandler(statsHandler);
ServletContextHandler statsContext = new ServletContextHandler(_contexts, "/stats");
statsContext.addServlet(new ServletHolder(new StatisticsServlet()), "/");
statsContext.setSessionHandler(new SessionHandler());
if (_statsPropFile != null)
{
final HashLoginService loginService = new HashLoginService("StatsRealm", _statsPropFile);
Constraint constraint = new Constraint();
constraint.setName("Admin Only");
constraint.setRoles(new String[]{"admin"});
constraint.setAuthenticate(true);
ConstraintMapping cm = new ConstraintMapping();
cm.setConstraint(constraint);
cm.setPathSpec("/*");
ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
securityHandler.setLoginService(loginService);
securityHandler.setConstraintMappings(Collections.singletonList(cm));
securityHandler.setAuthenticator(new BasicAuthenticator());
statsContext.setSecurityHandler(securityHandler);
}
}
}
//ensure a DefaultHandler is present
if (handlers.getChildHandlerByClass(DefaultHandler.class) == null)
{
handlers.addHandler(new DefaultHandler());
}
//check a connector is configured to listen on
Connector[] connectors = _server.getConnectors();
if (connectors == null || connectors.length == 0)
{
ServerConnector connector = new ServerConnector(_server);
connector.setPort(port);
if (host != null)
connector.setHost(host);
_server.addConnector(connector);
if (_enableStats)
connector.addBean(new ConnectionStatistics());
}
else
{
if (_enableStats)
{
for (Connector connector : connectors)
{
((AbstractConnector)connector).addBean(new ConnectionStatistics());
}
}
}
runnerServerInitialized = true;
}
// Create a context
try (Resource ctx = Resource.newResource(args[i]))
{
if (!ctx.exists())
usage("Context '" + ctx + "' does not exist");
if (contextPathSet && !(contextPath.startsWith("/")))
contextPath = "/" + contextPath;
// Configure the context
if (!ctx.isDirectory() && ctx.toString().toLowerCase(Locale.ENGLISH).endsWith(".xml"))
{
// It is a context config file
XmlConfiguration xmlConfiguration = new XmlConfiguration(ctx);
xmlConfiguration.getIdMap().put("Server", _server);
ContextHandler handler = (ContextHandler)xmlConfiguration.configure();
if (contextPathSet)
handler.setContextPath(contextPath);
_contexts.addHandler(handler);
String containerIncludeJarPattern = (String)handler.getAttribute(MetaInfConfiguration.CONTAINER_JAR_PATTERN);
if (containerIncludeJarPattern == null)
containerIncludeJarPattern = CONTAINER_INCLUDE_JAR_PATTERN;
else
{
if (!containerIncludeJarPattern.contains(CONTAINER_INCLUDE_JAR_PATTERN))
{
containerIncludeJarPattern = containerIncludeJarPattern + (StringUtil.isBlank(containerIncludeJarPattern) ? "" : "|") + CONTAINER_INCLUDE_JAR_PATTERN;
}
}
handler.setAttribute(MetaInfConfiguration.CONTAINER_JAR_PATTERN, containerIncludeJarPattern);
//check the configurations, if not explicitly set up, then configure all of them
if (handler instanceof WebAppContext)
{
WebAppContext wac = (WebAppContext)handler;
if (wac.getConfigurationClasses() == null || wac.getConfigurationClasses().length == 0)
wac.setConfigurationClasses(PLUS_CONFIGURATION_CLASSES);
}
}
else
{
// assume it is a WAR file
WebAppContext webapp = new WebAppContext(_contexts, ctx.toString(), contextPath);
webapp.setConfigurationClasses(PLUS_CONFIGURATION_CLASSES);
webapp.setAttribute(MetaInfConfiguration.CONTAINER_JAR_PATTERN,
CONTAINER_INCLUDE_JAR_PATTERN);
}
}
//reset
contextPathSet = false;
contextPath = DEFAULT_CONTEXT_PATH;
break;
}
}
if (_server == null)
usage("No Contexts defined");
_server.setStopAtShutdown(true);
switch ((stopPort > 0 ? 1 : 0) + (stopKey != null ? 2 : 0))
{
case 1:
usage("Must specify --stop-key when --stop-port is specified");
break;
case 2:
usage("Must specify --stop-port when --stop-key is specified");
break;
case 3:
ShutdownMonitor monitor = ShutdownMonitor.getInstance();
monitor.setPort(stopPort);
monitor.setKey(stopKey);
monitor.setExitVm(true);
break;
default:
break;
}
if (_logFile != null)
{
CustomRequestLog requestLog = new CustomRequestLog(_logFile);
_server.setRequestLog(requestLog);
}
}
protected void prependHandler(Handler handler, HandlerCollection handlers)
{
if (handler == null || handlers == null)
return;
Handler[] existing = handlers.getChildHandlers();
Handler[] children = new Handler[existing.length + 1];
children[0] = handler;
System.arraycopy(existing, 0, children, 1, existing.length);
handlers.setHandlers(children);
}
public void run() throws Exception
{
_server.start();
_server.join();
}
private URL toURL(URI uri)
{
try
{
return uri.toURL();
}
catch (MalformedURLException e)
{
throw new RuntimeException(e);
}
}
/**
* Establish a classloader with custom paths (if any)
*/
protected void initClassLoader()
{
URL[] paths = Arrays.stream(_classpath.asArray()).map(this::toURL).toArray(URL[]::new);
if (_classLoader == null && paths.length > 0)
{
ClassLoader context = Thread.currentThread().getContextClassLoader();
if (context == null)
{
_classLoader = new URLClassLoader(paths);
}
else
{
_classLoader = new URLClassLoader(paths, context);
}
Thread.currentThread().setContextClassLoader(_classLoader);
}
}
public static void main(String[] args)
{
System.err.println("WARNING: jetty-runner is deprecated.");
System.err.println(" See Jetty Documentation for startup options");
System.err.println(" https://www.eclipse.org/jetty/documentation/");
Runner runner = new Runner();
try
{
if (args.length > 0 && args[0].equalsIgnoreCase("--help"))
{
runner.usage(null);
}
else if (args.length > 0 && args[0].equalsIgnoreCase("--version"))
{
runner.version();
}
else
{
runner.configure(args);
runner.run();
}
}
catch (Exception e)
{
e.printStackTrace();
runner.usage(null);
}
}
}

View File

@ -1,23 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// 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
// ========================================================================
//
/**
* Jetty Runner : Embedded Jetty Tool for running webapps directly
*/
package org.eclipse.jetty.runner;

View File

@ -1 +0,0 @@
Comment: Jetty Runner

View File

@ -132,7 +132,6 @@
<module>examples</module>
<module>jetty-quickstart</module>
<module>jetty-distribution</module>
<module>jetty-runner</module>
<module>jetty-http-spi</module>
<module>jetty-osgi</module>
<module>jetty-alpn</module>