Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-10.0.x-1743-refactor-maven-plugin-redux
Signed-off-by: Jan Bartel <janb@webtide.com>
This commit is contained in:
commit
08790a45a4
|
@ -51,6 +51,17 @@ pipeline {
|
|||
}
|
||||
}
|
||||
|
||||
stage("Build / Test - JDK13") {
|
||||
agent { node { label 'linux' } }
|
||||
steps {
|
||||
timeout(time: 120, unit: 'MINUTES') {
|
||||
mavenBuild("jdk13", "-Pmongodb install", "maven3", true)
|
||||
warnings consoleParsers: [[parserName: 'Maven'], [parserName: 'Java']]
|
||||
junit testResults: '**/target/surefire-reports/*.xml,**/target/invoker-reports/TEST*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage("Build Javadoc") {
|
||||
agent { node { label 'linux' } }
|
||||
steps {
|
||||
|
|
|
@ -152,17 +152,7 @@ public class HttpConnectionOverHTTP extends AbstractConnection implements IConne
|
|||
@Override
|
||||
public void onFillable()
|
||||
{
|
||||
HttpExchange exchange = channel.getHttpExchange();
|
||||
if (exchange != null)
|
||||
{
|
||||
channel.receive();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is no exchange, then could be either a remote close,
|
||||
// or garbage bytes; in both cases we close the connection
|
||||
close();
|
||||
}
|
||||
channel.receive();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -50,12 +50,6 @@ public class HttpTransportOverFCGI implements HttpTransport
|
|||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(MetaData.Request request, MetaData.Response response, ByteBuffer content, boolean lastContent, Callback callback)
|
||||
{
|
||||
|
|
|
@ -56,6 +56,8 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
|
|||
private final ISession session;
|
||||
private final int bufferSize;
|
||||
private final ExecutionStrategy strategy;
|
||||
private boolean useInputDirectByteBuffers;
|
||||
private boolean useOutputDirectByteBuffers;
|
||||
|
||||
public HTTP2Connection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, Parser parser, ISession session, int bufferSize)
|
||||
{
|
||||
|
@ -99,6 +101,26 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
|
|||
producer.setInputBuffer(buffer);
|
||||
}
|
||||
|
||||
public boolean isUseInputDirectByteBuffers()
|
||||
{
|
||||
return useInputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseInputDirectByteBuffers(boolean useInputDirectByteBuffers)
|
||||
{
|
||||
this.useInputDirectByteBuffers = useInputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public boolean isUseOutputDirectByteBuffers()
|
||||
{
|
||||
return useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseOutputDirectByteBuffers(boolean useOutputDirectByteBuffers)
|
||||
{
|
||||
this.useOutputDirectByteBuffers = useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen()
|
||||
{
|
||||
|
@ -389,7 +411,7 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
|
|||
{
|
||||
private NetworkBuffer()
|
||||
{
|
||||
super(byteBufferPool, bufferSize, false);
|
||||
super(byteBufferPool, bufferSize, isUseInputDirectByteBuffers());
|
||||
}
|
||||
|
||||
private void put(ByteBuffer source)
|
||||
|
|
|
@ -493,12 +493,6 @@ public abstract class HTTP2StreamEndPoint implements EndPoint
|
|||
LOG.debug("onClose {}", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgrade(Connection newConnection)
|
||||
{
|
||||
|
|
|
@ -44,4 +44,9 @@ public abstract class FrameGenerator
|
|||
{
|
||||
return headerGenerator.getMaxFrameSize();
|
||||
}
|
||||
|
||||
public boolean isUseDirectByteBuffers()
|
||||
{
|
||||
return headerGenerator.isUseDirectByteBuffers();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,10 +38,15 @@ public class Generator
|
|||
}
|
||||
|
||||
public Generator(ByteBufferPool byteBufferPool, int maxDynamicTableSize, int maxHeaderBlockFragment)
|
||||
{
|
||||
this(byteBufferPool, true, maxDynamicTableSize, maxHeaderBlockFragment);
|
||||
}
|
||||
|
||||
public Generator(ByteBufferPool byteBufferPool, boolean useDirectByteBuffers, int maxDynamicTableSize, int maxHeaderBlockFragment)
|
||||
{
|
||||
this.byteBufferPool = byteBufferPool;
|
||||
|
||||
headerGenerator = new HeaderGenerator();
|
||||
headerGenerator = new HeaderGenerator(useDirectByteBuffers);
|
||||
hpackEncoder = new HpackEncoder(maxDynamicTableSize);
|
||||
|
||||
this.generators = new FrameGenerator[FrameType.values().length];
|
||||
|
|
|
@ -27,10 +27,26 @@ import org.eclipse.jetty.io.ByteBufferPool;
|
|||
public class HeaderGenerator
|
||||
{
|
||||
private int maxFrameSize = Frame.DEFAULT_MAX_LENGTH;
|
||||
private final boolean useDirectByteBuffers;
|
||||
|
||||
public HeaderGenerator()
|
||||
{
|
||||
this(true);
|
||||
}
|
||||
|
||||
public HeaderGenerator(boolean useDirectByteBuffers)
|
||||
{
|
||||
this.useDirectByteBuffers = useDirectByteBuffers;
|
||||
}
|
||||
|
||||
public boolean isUseDirectByteBuffers()
|
||||
{
|
||||
return useDirectByteBuffers;
|
||||
}
|
||||
|
||||
public ByteBuffer generate(ByteBufferPool.Lease lease, FrameType frameType, int capacity, int length, int flags, int streamId)
|
||||
{
|
||||
ByteBuffer header = lease.acquire(capacity, true);
|
||||
ByteBuffer header = lease.acquire(capacity, isUseDirectByteBuffers());
|
||||
header.put((byte)((length & 0x00_FF_00_00) >>> 16));
|
||||
header.put((byte)((length & 0x00_00_FF_00) >>> 8));
|
||||
header.put((byte)((length & 0x00_00_00_FF)));
|
||||
|
|
|
@ -67,7 +67,7 @@ public class HeadersGenerator extends FrameGenerator
|
|||
flags = Flags.PRIORITY;
|
||||
|
||||
int maxFrameSize = getMaxFrameSize();
|
||||
ByteBuffer hpacked = lease.acquire(maxFrameSize, false);
|
||||
ByteBuffer hpacked = lease.acquire(maxFrameSize, isUseDirectByteBuffers());
|
||||
BufferUtil.clearToFill(hpacked);
|
||||
encoder.encode(hpacked, metaData);
|
||||
int hpackedLength = hpacked.position();
|
||||
|
|
|
@ -58,7 +58,7 @@ public class PushPromiseGenerator extends FrameGenerator
|
|||
int extraSpace = 4;
|
||||
maxFrameSize -= extraSpace;
|
||||
|
||||
ByteBuffer hpacked = lease.acquire(maxFrameSize, false);
|
||||
ByteBuffer hpacked = lease.acquire(maxFrameSize, isUseDirectByteBuffers());
|
||||
BufferUtil.clearToFill(hpacked);
|
||||
encoder.encode(hpacked, metaData);
|
||||
int hpackedLength = hpacked.position();
|
||||
|
|
|
@ -25,7 +25,7 @@ import org.eclipse.jetty.http.HttpHeader;
|
|||
import org.eclipse.jetty.http.HttpTokens;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
@ -77,13 +77,8 @@ public class HpackDecoder
|
|||
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
if (LOG.isDebugEnabled() && buffer.hasArray())
|
||||
{
|
||||
int l = Math.min(buffer.remaining(), 32);
|
||||
LOG.debug("decode {}{}",
|
||||
TypeUtil.toHexString(buffer.array(), buffer.arrayOffset() + buffer.position(), l),
|
||||
l < buffer.remaining() ? "..." : "");
|
||||
}
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("decode {}", BufferUtil.toHexString(buffer));
|
||||
|
||||
byte b = buffer.get();
|
||||
if (b < 0)
|
||||
|
@ -280,14 +275,9 @@ public class HpackDecoder
|
|||
public static String toASCIIString(ByteBuffer buffer, int length)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(length);
|
||||
int position = buffer.position();
|
||||
int start = buffer.arrayOffset() + position;
|
||||
int end = start + length;
|
||||
buffer.position(position + length);
|
||||
byte[] array = buffer.array();
|
||||
for (int i = start; i < end; i++)
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
builder.append((char)(0x7f & array[i]));
|
||||
builder.append((char)(0x7F & buffer.get()));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.eclipse.jetty.http.MetaData;
|
|||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
|
||||
import org.eclipse.jetty.http2.hpack.HpackContext.StaticEntry;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -363,9 +364,8 @@ public class HpackEncoder
|
|||
|
||||
if (_debug)
|
||||
{
|
||||
int e = buffer.position();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("encode {}:'{}' to '{}'", encoding, field, TypeUtil.toHexString(buffer.array(), buffer.arrayOffset() + p, e - p));
|
||||
LOG.debug("encode {}:'{}' to '{}'", encoding, field, BufferUtil.toHexString(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,8 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
private RateControl rateControl = new WindowRateControl(20, Duration.ofSeconds(1));
|
||||
private FlowControlStrategy.Factory flowControlStrategyFactory = () -> new BufferingFlowControlStrategy(0.5F);
|
||||
private long streamIdleTimeout;
|
||||
private boolean _useInputDirectByteBuffers;
|
||||
private boolean _useOutputDirectByteBuffers;
|
||||
|
||||
public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration)
|
||||
{
|
||||
|
@ -82,6 +84,8 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
this.httpConfiguration = Objects.requireNonNull(httpConfiguration);
|
||||
addBean(httpConfiguration);
|
||||
setInputBufferSize(Frame.DEFAULT_MAX_LENGTH + Frame.HEADER_LENGTH);
|
||||
setUseInputDirectByteBuffers(httpConfiguration.isUseInputDirectByteBuffers());
|
||||
setUseOutputDirectByteBuffers(httpConfiguration.isUseOutputDirectByteBuffers());
|
||||
}
|
||||
|
||||
@ManagedAttribute("The HPACK dynamic table maximum size")
|
||||
|
@ -192,6 +196,26 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
this.rateControl = rateControl;
|
||||
}
|
||||
|
||||
public boolean isUseInputDirectByteBuffers()
|
||||
{
|
||||
return _useInputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseInputDirectByteBuffers(boolean useInputDirectByteBuffers)
|
||||
{
|
||||
_useInputDirectByteBuffers = useInputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public boolean isUseOutputDirectByteBuffers()
|
||||
{
|
||||
return _useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseOutputDirectByteBuffers(boolean useOutputDirectByteBuffers)
|
||||
{
|
||||
_useOutputDirectByteBuffers = useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public HttpConfiguration getHttpConfiguration()
|
||||
{
|
||||
return httpConfiguration;
|
||||
|
@ -214,7 +238,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
{
|
||||
ServerSessionListener listener = newSessionListener(connector, endPoint);
|
||||
|
||||
Generator generator = new Generator(connector.getByteBufferPool(), getMaxDynamicTableSize(), getMaxHeaderBlockFragment());
|
||||
Generator generator = new Generator(connector.getByteBufferPool(), isUseOutputDirectByteBuffers(), getMaxDynamicTableSize(), getMaxHeaderBlockFragment());
|
||||
FlowControlStrategy flowControl = getFlowControlStrategyFactory().newFlowControlStrategy();
|
||||
HTTP2ServerSession session = new HTTP2ServerSession(connector.getScheduler(), endPoint, generator, listener, flowControl);
|
||||
session.setMaxLocalStreams(getMaxConcurrentStreams());
|
||||
|
@ -235,6 +259,8 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
|
||||
HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(),
|
||||
endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
|
||||
connection.setUseInputDirectByteBuffers(isUseInputDirectByteBuffers());
|
||||
connection.setUseOutputDirectByteBuffers(isUseOutputDirectByteBuffers());
|
||||
connection.addListener(sessionContainer);
|
||||
return configure(connection, connector, endPoint);
|
||||
}
|
||||
|
|
|
@ -289,6 +289,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
HttpTransportOverHTTP2 transport = new HttpTransportOverHTTP2(connector, this);
|
||||
transport.setStream(stream);
|
||||
channel = newServerHttpChannelOverHTTP2(connector, httpConfig, transport);
|
||||
channel.setUseOutputDirectByteBuffers(isUseOutputDirectByteBuffers());
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Creating channel {} for {}", channel, this);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ public class HttpChannelOverHTTP2 extends HttpChannel implements Closeable, Writ
|
|||
|
||||
private boolean _expect100Continue;
|
||||
private boolean _delayedUntilContent;
|
||||
private boolean _useOutputDirectByteBuffers;
|
||||
|
||||
public HttpChannelOverHTTP2(Connector connector, HttpConfiguration configuration, EndPoint endPoint, HttpTransportOverHTTP2 transport)
|
||||
{
|
||||
|
@ -68,6 +69,17 @@ public class HttpChannelOverHTTP2 extends HttpChannel implements Closeable, Writ
|
|||
return getHttpTransport().getStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseOutputDirectByteBuffers()
|
||||
{
|
||||
return _useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseOutputDirectByteBuffers(boolean useOutputDirectByteBuffers)
|
||||
{
|
||||
_useOutputDirectByteBuffers = useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpecting100Continue()
|
||||
{
|
||||
|
|
|
@ -62,14 +62,6 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
|||
this.connection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
// Because sent buffers are passed directly to the endpoint without
|
||||
// copying we can defer to the endpoint
|
||||
return connection.getEndPoint().isOptimizedForDirectBuffers();
|
||||
}
|
||||
|
||||
public IStream getStream()
|
||||
{
|
||||
return stream;
|
||||
|
|
|
@ -327,12 +327,6 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
_connection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void reset()
|
||||
{
|
||||
_state.set(State.OPEN);
|
||||
|
|
|
@ -175,12 +175,6 @@ public abstract class ChannelEndPoint extends AbstractEndPoint implements Manage
|
|||
_gather = (channel instanceof GatheringByteChannel) ? (GatheringByteChannel)channel : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen()
|
||||
{
|
||||
|
|
|
@ -269,13 +269,6 @@ public interface EndPoint extends Closeable
|
|||
*/
|
||||
void onClose(Throwable cause);
|
||||
|
||||
/**
|
||||
* Is the endpoint optimized for DirectBuffer usage
|
||||
*
|
||||
* @return True if direct buffers can be used optimally.
|
||||
*/
|
||||
boolean isOptimizedForDirectBuffers();
|
||||
|
||||
/**
|
||||
* Upgrade connections.
|
||||
* Close the old connection, update the endpoint and open the new connection.
|
||||
|
|
|
@ -95,7 +95,6 @@ public class SslClientConnectionFactory implements ClientConnectionFactory
|
|||
context.put(SSL_ENGINE_CONTEXT_KEY, engine);
|
||||
|
||||
SslConnection sslConnection = newSslConnection(byteBufferPool, executor, endPoint, engine);
|
||||
endPoint.setConnection(sslConnection);
|
||||
|
||||
EndPoint appEndPoint = sslConnection.getDecryptedEndPoint();
|
||||
appEndPoint.setConnection(connectionFactory.newConnection(appEndPoint, context));
|
||||
|
|
|
@ -42,10 +42,10 @@ import org.eclipse.jetty.util.StringUtil;
|
|||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.resource.PathResource;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.util.resource.ResourceCollection;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.Configurations;
|
||||
import org.eclipse.jetty.webapp.MetaInfConfiguration;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
|
@ -303,22 +303,27 @@ public class JettyWebAppContext extends WebAppContext
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void loadConfigurations()
|
||||
protected Configurations newConfigurations()
|
||||
{
|
||||
super.loadConfigurations();
|
||||
try
|
||||
Configurations configurations = super.newConfigurations();
|
||||
if (getJettyEnvXml() != null)
|
||||
{
|
||||
// inject configurations with config from maven plugin
|
||||
for (Configuration c : getWebAppConfigurations())
|
||||
try
|
||||
{
|
||||
if (c instanceof EnvConfiguration && getJettyEnvXml() != null)
|
||||
((EnvConfiguration)c).setJettyEnvResource(new PathResource(new File(getJettyEnvXml())));
|
||||
// inject configurations with config from maven plugin
|
||||
for (Configuration c : configurations)
|
||||
{
|
||||
if (c instanceof EnvConfiguration)
|
||||
((EnvConfiguration)c).setJettyEnvResource(Resource.newResource(getJettyEnvXml()));
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return configurations;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -85,7 +85,7 @@ public class QuickStartConfiguration extends AbstractConfiguration
|
|||
|
||||
public QuickStartConfiguration()
|
||||
{
|
||||
super(false);
|
||||
super(true);
|
||||
addDependencies(WebInfConfiguration.class);
|
||||
addDependents(WebXmlConfiguration.class);
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ public class QuickStartConfiguration extends AbstractConfiguration
|
|||
{
|
||||
LOG.info("Quickstarting {}", context);
|
||||
_quickStart = true;
|
||||
context.setConfigurations(context.getWebAppConfigurations().stream()
|
||||
context.setConfigurations(context.getConfigurations().stream()
|
||||
.filter(c -> !__replacedConfigurations.contains(c.replaces()) && !__replacedConfigurations.contains(c.getClass()))
|
||||
.collect(Collectors.toList()).toArray(new Configuration[]{}));
|
||||
context.getMetaData().setWebXml((Resource)context.getAttribute(QUICKSTART_WEB_XML));
|
||||
|
|
|
@ -93,7 +93,7 @@ public class QuickStartGeneratorConfiguration extends AbstractConfiguration
|
|||
|
||||
public QuickStartGeneratorConfiguration(boolean abort)
|
||||
{
|
||||
super(true);
|
||||
super(false);
|
||||
_count = 0;
|
||||
_abort = abort;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,11 @@
|
|||
<!-- =========================================================== -->
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.util.thread.ScheduledExecutorScheduler"/>
|
||||
<New class="org.eclipse.jetty.util.thread.ScheduledExecutorScheduler">
|
||||
<Arg name="name"><Property name="jetty.scheduler.name"/></Arg>
|
||||
<Arg name="daemon" type="boolean"><Property name="jetty.scheduler.daemon" default="false" /></Arg>
|
||||
<Arg name="threads" type="int"><Property name="jetty.scheduler.threads" default="-1" /></Arg>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
|
||||
|
||||
[jpms]
|
||||
add-modules: java.sql
|
|
@ -80,3 +80,8 @@ etc/jetty.xml
|
|||
|
||||
## Dump the state of the Jetty server, components, and webapps before shutdown
|
||||
# jetty.server.dumpBeforeStop=false
|
||||
|
||||
## Scheduler Configuration
|
||||
# jetty.scheduler.name=
|
||||
# jetty.scheduler.deamon=false
|
||||
# jetty.scheduler.threads=-1
|
||||
|
|
|
@ -10,6 +10,7 @@ session
|
|||
session-store
|
||||
|
||||
[depend]
|
||||
jdbc
|
||||
sessions
|
||||
sessions/jdbc/${db-connection-type}
|
||||
|
||||
|
@ -54,7 +55,3 @@ db-connection-type=datasource
|
|||
#jetty.session.jdbc.schema.maxIntervalColumn=maxInterval
|
||||
#jetty.session.jdbc.schema.mapColumn=map
|
||||
#jetty.session.jdbc.schema.table=JettySessions
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,5 +3,8 @@ DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-m
|
|||
[description]
|
||||
JDBC Datasource connections for session storage
|
||||
|
||||
[depends]
|
||||
jdbc
|
||||
|
||||
[xml]
|
||||
etc/sessions/jdbc/datasource.xml
|
||||
|
|
|
@ -3,5 +3,8 @@ DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-m
|
|||
[description]
|
||||
JDBC Driver connections for session storage
|
||||
|
||||
[depend]
|
||||
jdbc
|
||||
|
||||
[xml]
|
||||
etc/sessions/jdbc/driver.xml
|
||||
|
|
|
@ -44,7 +44,6 @@ import org.eclipse.jetty.http.HttpStatus;
|
|||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ChannelEndPoint;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.QuietException;
|
||||
|
@ -251,12 +250,6 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
return _configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
return getHttpTransport().isOptimizedForDirectBuffers();
|
||||
}
|
||||
|
||||
public Server getServer()
|
||||
{
|
||||
return _connector.getServer();
|
||||
|
@ -971,12 +964,9 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
return _connector.getScheduler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the HttpChannel can efficiently use direct buffer (typically this means it is not over SSL or a multiplexed protocol)
|
||||
*/
|
||||
public boolean useDirectBuffers()
|
||||
public boolean isUseOutputDirectByteBuffers()
|
||||
{
|
||||
return getEndPoint() instanceof ChannelEndPoint;
|
||||
return getHttpConfiguration().isUseOutputDirectByteBuffers();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -69,6 +69,12 @@ public class HttpChannelOverHttp extends HttpChannel implements HttpParser.Reque
|
|||
_metadata.setURI(new HttpURI());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseOutputDirectByteBuffers()
|
||||
{
|
||||
return _httpConnection.isUseOutputDirectByteBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpInput newHttpInput(HttpChannelState state)
|
||||
{
|
||||
|
|
|
@ -67,7 +67,8 @@ public class HttpConfiguration implements Dumpable
|
|||
private boolean _delayDispatchUntilContent = true;
|
||||
private boolean _persistentConnectionsEnabled = true;
|
||||
private int _maxErrorDispatches = 10;
|
||||
private boolean _useDirectByteBuffers = false;
|
||||
private boolean _useInputDirectByteBuffers = true;
|
||||
private boolean _useOutputDirectByteBuffers = true;
|
||||
private long _minRequestDataRate;
|
||||
private long _minResponseDataRate;
|
||||
private HttpCompliance _httpCompliance = HttpCompliance.RFC7230;
|
||||
|
@ -134,7 +135,8 @@ public class HttpConfiguration implements Dumpable
|
|||
_delayDispatchUntilContent = config._delayDispatchUntilContent;
|
||||
_persistentConnectionsEnabled = config._persistentConnectionsEnabled;
|
||||
_maxErrorDispatches = config._maxErrorDispatches;
|
||||
_useDirectByteBuffers = config._useDirectByteBuffers;
|
||||
_useInputDirectByteBuffers = config._useInputDirectByteBuffers;
|
||||
_useOutputDirectByteBuffers = config._useOutputDirectByteBuffers;
|
||||
_minRequestDataRate = config._minRequestDataRate;
|
||||
_minResponseDataRate = config._minResponseDataRate;
|
||||
_httpCompliance = config._httpCompliance;
|
||||
|
@ -327,17 +329,31 @@ public class HttpConfiguration implements Dumpable
|
|||
}
|
||||
|
||||
/**
|
||||
* @param useDirectByteBuffers if true, use direct byte buffers for requests
|
||||
* @param useInputDirectByteBuffers whether to use direct ByteBuffers for reading
|
||||
*/
|
||||
public void setUseDirectByteBuffers(boolean useDirectByteBuffers)
|
||||
public void setUseInputDirectByteBuffers(boolean useInputDirectByteBuffers)
|
||||
{
|
||||
_useDirectByteBuffers = useDirectByteBuffers;
|
||||
_useInputDirectByteBuffers = useInputDirectByteBuffers;
|
||||
}
|
||||
|
||||
@ManagedAttribute("Whether to use direct byte buffers for requests")
|
||||
public boolean isUseDirectByteBuffers()
|
||||
@ManagedAttribute("Whether to use direct ByteBuffers for reading")
|
||||
public boolean isUseInputDirectByteBuffers()
|
||||
{
|
||||
return _useDirectByteBuffers;
|
||||
return _useInputDirectByteBuffers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useOutputDirectByteBuffers whether to use direct ByteBuffers for writing
|
||||
*/
|
||||
public void setUseOutputDirectByteBuffers(boolean useOutputDirectByteBuffers)
|
||||
{
|
||||
_useOutputDirectByteBuffers = useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
@ManagedAttribute("Whether to use direct ByteBuffers for writing")
|
||||
public boolean isUseOutputDirectByteBuffers()
|
||||
{
|
||||
return _useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -72,6 +72,8 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
private final boolean _recordHttpComplianceViolations;
|
||||
private final LongAdder bytesIn = new LongAdder();
|
||||
private final LongAdder bytesOut = new LongAdder();
|
||||
private boolean _useInputDirectByteBuffers;
|
||||
private boolean _useOutputDirectByteBuffers;
|
||||
|
||||
/**
|
||||
* Get the current connection that this thread is dispatched to.
|
||||
|
@ -163,12 +165,6 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
return _generator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
return getEndPoint().isOptimizedForDirectBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMessagesIn()
|
||||
{
|
||||
|
@ -181,6 +177,26 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
return getHttpChannel().getRequests();
|
||||
}
|
||||
|
||||
public boolean isUseInputDirectByteBuffers()
|
||||
{
|
||||
return _useInputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseInputDirectByteBuffers(boolean useInputDirectByteBuffers)
|
||||
{
|
||||
_useInputDirectByteBuffers = useInputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public boolean isUseOutputDirectByteBuffers()
|
||||
{
|
||||
return _useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseOutputDirectByteBuffers(boolean useOutputDirectByteBuffers)
|
||||
{
|
||||
_useOutputDirectByteBuffers = useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer onUpgradeFrom()
|
||||
{
|
||||
|
@ -223,7 +239,10 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
public ByteBuffer getRequestBuffer()
|
||||
{
|
||||
if (_requestBuffer == null)
|
||||
_requestBuffer = _bufferPool.acquire(getInputBufferSize(), _config.isUseDirectByteBuffers());
|
||||
{
|
||||
boolean useDirectByteBuffers = isUseInputDirectByteBuffers();
|
||||
_requestBuffer = _bufferPool.acquire(getInputBufferSize(), useDirectByteBuffers);
|
||||
}
|
||||
return _requestBuffer;
|
||||
}
|
||||
|
||||
|
@ -731,6 +750,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
if (_callback == null)
|
||||
throw new IllegalStateException();
|
||||
|
||||
boolean useDirectByteBuffers = isUseOutputDirectByteBuffers();
|
||||
ByteBuffer chunk = _chunk;
|
||||
while (true)
|
||||
{
|
||||
|
@ -751,19 +771,19 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
|
||||
case NEED_HEADER:
|
||||
{
|
||||
_header = _bufferPool.acquire(_config.getResponseHeaderSize(), _config.isUseDirectByteBuffers());
|
||||
_header = _bufferPool.acquire(_config.getResponseHeaderSize(), useDirectByteBuffers);
|
||||
continue;
|
||||
}
|
||||
case NEED_CHUNK:
|
||||
{
|
||||
chunk = _chunk = _bufferPool.acquire(HttpGenerator.CHUNK_SIZE, _config.isUseDirectByteBuffers());
|
||||
chunk = _chunk = _bufferPool.acquire(HttpGenerator.CHUNK_SIZE, useDirectByteBuffers);
|
||||
continue;
|
||||
}
|
||||
case NEED_CHUNK_TRAILER:
|
||||
{
|
||||
if (_chunk != null)
|
||||
_bufferPool.release(_chunk);
|
||||
chunk = _chunk = _bufferPool.acquire(_config.getResponseHeaderSize(), _config.isUseDirectByteBuffers());
|
||||
chunk = _chunk = _bufferPool.acquire(_config.getResponseHeaderSize(), useDirectByteBuffers);
|
||||
continue;
|
||||
}
|
||||
case FLUSH:
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
@ -32,7 +34,9 @@ import org.eclipse.jetty.util.annotation.Name;
|
|||
public class HttpConnectionFactory extends AbstractConnectionFactory implements HttpConfiguration.ConnectionFactory
|
||||
{
|
||||
private final HttpConfiguration _config;
|
||||
private boolean _recordHttpComplianceViolations = false;
|
||||
private boolean _recordHttpComplianceViolations;
|
||||
private boolean _useInputDirectByteBuffers;
|
||||
private boolean _useOutputDirectByteBuffers;
|
||||
|
||||
public HttpConnectionFactory()
|
||||
{
|
||||
|
@ -42,10 +46,10 @@ public class HttpConnectionFactory extends AbstractConnectionFactory implements
|
|||
public HttpConnectionFactory(@Name("config") HttpConfiguration config)
|
||||
{
|
||||
super(HttpVersion.HTTP_1_1.asString());
|
||||
_config = config;
|
||||
if (config == null)
|
||||
throw new IllegalArgumentException("Null HttpConfiguration");
|
||||
_config = Objects.requireNonNull(config);
|
||||
addBean(_config);
|
||||
setUseInputDirectByteBuffers(_config.isUseInputDirectByteBuffers());
|
||||
setUseOutputDirectByteBuffers(_config.isUseOutputDirectByteBuffers());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -59,15 +63,37 @@ public class HttpConnectionFactory extends AbstractConnectionFactory implements
|
|||
return _recordHttpComplianceViolations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection newConnection(Connector connector, EndPoint endPoint)
|
||||
{
|
||||
HttpConnection conn = new HttpConnection(_config, connector, endPoint, isRecordHttpComplianceViolations());
|
||||
return configure(conn, connector, endPoint);
|
||||
}
|
||||
|
||||
public void setRecordHttpComplianceViolations(boolean recordHttpComplianceViolations)
|
||||
{
|
||||
this._recordHttpComplianceViolations = recordHttpComplianceViolations;
|
||||
}
|
||||
|
||||
public boolean isUseInputDirectByteBuffers()
|
||||
{
|
||||
return _useInputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseInputDirectByteBuffers(boolean useInputDirectByteBuffers)
|
||||
{
|
||||
_useInputDirectByteBuffers = useInputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public boolean isUseOutputDirectByteBuffers()
|
||||
{
|
||||
return _useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseOutputDirectByteBuffers(boolean useOutputDirectByteBuffers)
|
||||
{
|
||||
_useOutputDirectByteBuffers = useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection newConnection(Connector connector, EndPoint endPoint)
|
||||
{
|
||||
HttpConnection connection = new HttpConnection(_config, connector, endPoint, isRecordHttpComplianceViolations());
|
||||
connection.setUseInputDirectByteBuffers(isUseInputDirectByteBuffers());
|
||||
connection.setUseOutputDirectByteBuffers(isUseOutputDirectByteBuffers());
|
||||
return configure(connection, connector, endPoint);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,14 +127,6 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
*/
|
||||
Interceptor getNextInterceptor();
|
||||
|
||||
/**
|
||||
* @return True if the Interceptor is optimized to receive direct
|
||||
* {@link ByteBuffer}s in the {@link #write(ByteBuffer, boolean, Callback)}
|
||||
* method. If false is returned, then passing direct buffers may cause
|
||||
* inefficiencies.
|
||||
*/
|
||||
boolean isOptimizedForDirectBuffers();
|
||||
|
||||
/**
|
||||
* Reset the buffers.
|
||||
* <p>If the Interceptor contains buffers then reset them.
|
||||
|
@ -417,7 +409,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
public ByteBuffer acquireBuffer()
|
||||
{
|
||||
if (_aggregate == null)
|
||||
_aggregate = _channel.getByteBufferPool().acquire(getBufferSize(), _interceptor.isOptimizedForDirectBuffers());
|
||||
_aggregate = _channel.getByteBufferPool().acquire(getBufferSize(), _channel.isUseOutputDirectByteBuffers());
|
||||
return _aggregate;
|
||||
}
|
||||
|
||||
|
@ -591,7 +583,6 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
// handle blocking write
|
||||
|
||||
// Should we aggregate?
|
||||
int capacity = getBufferSize();
|
||||
boolean last = isLastContentToWrite(len);
|
||||
if (!last && len <= _commitSize)
|
||||
{
|
||||
|
@ -1065,7 +1056,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
break;
|
||||
}
|
||||
|
||||
ByteBuffer buffer = _channel.useDirectBuffers() ? httpContent.getDirectBuffer() : null;
|
||||
ByteBuffer buffer = _channel.isUseOutputDirectByteBuffers() ? httpContent.getDirectBuffer() : null;
|
||||
if (buffer == null)
|
||||
buffer = httpContent.getIndirectBuffer();
|
||||
|
||||
|
@ -1483,6 +1474,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
{
|
||||
super(callback);
|
||||
_in = in;
|
||||
// Reading from InputStream requires byte[], don't use direct buffers.
|
||||
_buffer = _channel.getByteBufferPool().acquire(getBufferSize(), false);
|
||||
}
|
||||
|
||||
|
@ -1535,7 +1527,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
* An iterating callback that will take content from a
|
||||
* ReadableByteChannel and write it to the {@link HttpChannel}.
|
||||
* A {@link ByteBuffer} of size {@link HttpOutput#getBufferSize()} is used that will be direct if
|
||||
* {@link HttpChannel#useDirectBuffers()} is true.
|
||||
* {@link HttpChannel#isUseOutputDirectByteBuffers()} is true.
|
||||
* This callback is passed to the {@link HttpChannel#write(ByteBuffer, boolean, Callback)} to
|
||||
* be notified as each buffer is written and only once all the input is consumed will the
|
||||
* wrapped {@link Callback#succeeded()} method be called.
|
||||
|
@ -1550,7 +1542,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
{
|
||||
super(callback);
|
||||
_in = in;
|
||||
_buffer = _channel.getByteBufferPool().acquire(getBufferSize(), _channel.useDirectBuffers());
|
||||
_buffer = _channel.getByteBufferPool().acquire(getBufferSize(), _channel.isUseOutputDirectByteBuffers());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -73,11 +73,4 @@ public interface HttpTransport
|
|||
* @param failure the failure that caused the abort.
|
||||
*/
|
||||
void abort(Throwable failure);
|
||||
|
||||
/**
|
||||
* Is the underlying transport optimized for DirectBuffer usage
|
||||
*
|
||||
* @return True if direct buffers can be used optimally.
|
||||
*/
|
||||
boolean isOptimizedForDirectBuffers();
|
||||
}
|
||||
|
|
|
@ -601,12 +601,6 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory
|
|||
_local = local;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
return _endp.isOptimizedForDirectBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress()
|
||||
{
|
||||
|
|
|
@ -271,12 +271,6 @@ public class BufferedResponseHandler extends HandlerWrapper
|
|||
return _next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void commit(Queue<ByteBuffer> buffers, Callback callback)
|
||||
{
|
||||
// If only 1 buffer
|
||||
|
|
|
@ -93,12 +93,6 @@ public class GzipHttpOutputInterceptor implements HttpOutput.Interceptor
|
|||
return _interceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
return false; // No point as deflator is in user space.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuffer content, boolean complete, Callback callback)
|
||||
{
|
||||
|
|
|
@ -651,12 +651,6 @@ public class HttpOutputTest
|
|||
_next.write(BufferUtil.toBuffer(s), complete, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
return _next.isOptimizedForDirectBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interceptor getNextInterceptor()
|
||||
{
|
||||
|
|
|
@ -174,12 +174,6 @@ public class ResponseTest
|
|||
{
|
||||
_channelError = failure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,10 @@ import java.io.IOException;
|
|||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
|
||||
|
@ -40,6 +43,8 @@ public class ScheduledExecutorScheduler extends AbstractLifeCycle implements Sch
|
|||
private final boolean daemon;
|
||||
private final ClassLoader classloader;
|
||||
private final ThreadGroup threadGroup;
|
||||
private final int threads;
|
||||
private final AtomicInteger count = new AtomicInteger();
|
||||
private volatile ScheduledThreadPoolExecutor scheduler;
|
||||
private volatile Thread thread;
|
||||
|
||||
|
@ -50,28 +55,48 @@ public class ScheduledExecutorScheduler extends AbstractLifeCycle implements Sch
|
|||
|
||||
public ScheduledExecutorScheduler(String name, boolean daemon)
|
||||
{
|
||||
this(name, daemon, Thread.currentThread().getContextClassLoader());
|
||||
this(name, daemon, null);
|
||||
}
|
||||
|
||||
public ScheduledExecutorScheduler(String name, boolean daemon, ClassLoader threadFactoryClassLoader)
|
||||
public ScheduledExecutorScheduler(@Name("name") String name, @Name("daemon") boolean daemon, @Name("threads") int threads)
|
||||
{
|
||||
this(name, daemon, threadFactoryClassLoader, null);
|
||||
this(name, daemon, null, null, threads);
|
||||
}
|
||||
|
||||
public ScheduledExecutorScheduler(String name, boolean daemon, ClassLoader threadFactoryClassLoader, ThreadGroup threadGroup)
|
||||
public ScheduledExecutorScheduler(String name, boolean daemon, ClassLoader classLoader)
|
||||
{
|
||||
this.name = name == null ? "Scheduler-" + hashCode() : name;
|
||||
this(name, daemon, classLoader, null);
|
||||
}
|
||||
|
||||
public ScheduledExecutorScheduler(String name, boolean daemon, ClassLoader classLoader, ThreadGroup threadGroup)
|
||||
{
|
||||
this(name, daemon, classLoader, threadGroup, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name The name of the scheduler threads or null for automatic name
|
||||
* @param daemon True if scheduler threads should be daemon
|
||||
* @param classLoader The classloader to run the threads with or null to use the current thread context classloader
|
||||
* @param threadGroup The threadgroup to use or null for no thread group
|
||||
* @param threads The number of threads to pass to the the core {@link ScheduledThreadPoolExecutor} or -1 for a
|
||||
* heuristic determined number of threads.
|
||||
*/
|
||||
public ScheduledExecutorScheduler(@Name("name") String name, @Name("daemon") boolean daemon, @Name("classLoader") ClassLoader classLoader, @Name("threadGroup") ThreadGroup threadGroup, @Name("threads") int threads)
|
||||
{
|
||||
this.name = StringUtil.isBlank(name) ? "Scheduler-" + hashCode() : name;
|
||||
this.daemon = daemon;
|
||||
this.classloader = threadFactoryClassLoader == null ? Thread.currentThread().getContextClassLoader() : threadFactoryClassLoader;
|
||||
this.classloader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
|
||||
this.threadGroup = threadGroup;
|
||||
this.threads = threads;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
scheduler = new ScheduledThreadPoolExecutor(1, r ->
|
||||
int size = threads > 0 ? threads : 1;
|
||||
scheduler = new ScheduledThreadPoolExecutor(size, r ->
|
||||
{
|
||||
Thread thread = ScheduledExecutorScheduler.this.thread = new Thread(threadGroup, r, name);
|
||||
Thread thread = ScheduledExecutorScheduler.this.thread = new Thread(threadGroup, r, name + "-" + count.incrementAndGet());
|
||||
thread.setDaemon(daemon);
|
||||
thread.setContextClassLoader(classloader);
|
||||
return thread;
|
||||
|
|
|
@ -26,7 +26,7 @@ import java.util.stream.Collectors;
|
|||
|
||||
public class AbstractConfiguration implements Configuration
|
||||
{
|
||||
private final boolean _disabledByDefault;
|
||||
private final boolean _enabledByDefault;
|
||||
private final List<String> _after = new ArrayList<>();
|
||||
private final List<String> _beforeThis = new ArrayList<>();
|
||||
private final ClassMatcher _system = new ClassMatcher();
|
||||
|
@ -34,12 +34,12 @@ public class AbstractConfiguration implements Configuration
|
|||
|
||||
protected AbstractConfiguration()
|
||||
{
|
||||
this(false);
|
||||
this(true);
|
||||
}
|
||||
|
||||
protected AbstractConfiguration(boolean disabledByDefault)
|
||||
protected AbstractConfiguration(boolean enabledByDefault)
|
||||
{
|
||||
_disabledByDefault = disabledByDefault;
|
||||
_enabledByDefault = enabledByDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,9 +196,9 @@ public class AbstractConfiguration implements Configuration
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisabledByDefault()
|
||||
public boolean isEnabledByDefault()
|
||||
{
|
||||
return _disabledByDefault;
|
||||
return _enabledByDefault;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,12 +34,12 @@ import org.eclipse.jetty.util.TopologicalSort;
|
|||
* </p>
|
||||
* <p>Configuration instances are discovered by the {@link Configurations} class using either the
|
||||
* {@link ServiceLoader} mechanism or by an explicit call to {@link Configurations#setKnown(String...)}.
|
||||
* By default, all Configurations that do not implement the {@link #isDisabledByDefault()} interface
|
||||
* By default, all Configurations that do not return false from {@link #isEnabledByDefault()}
|
||||
* are applied to all {@link WebAppContext}s within the JVM. However a Server wide default {@link Configurations}
|
||||
* collection may also be defined with {@link Configurations#setServerDefault(org.eclipse.jetty.server.Server)}.
|
||||
* Furthermore, each individual Context may have its Configurations list explicitly set and/or amended with
|
||||
* {@link WebAppContext#setConfigurations(Configuration[])}, {@link WebAppContext#addConfiguration(Configuration...)}
|
||||
* or {@link WebAppContext#getWebAppConfigurations()}.
|
||||
* or {@link WebAppContext#getConfigurations()}.
|
||||
* </p>
|
||||
* <p>Since Jetty-9.4, Configurations are self ordering using the {@link #getDependencies()} and
|
||||
* {@link #getDependents()} methods for a {@link TopologicalSort} initiated by {@link Configurations#sort()}
|
||||
|
@ -171,9 +171,9 @@ public interface Configuration
|
|||
void destroy(WebAppContext context) throws Exception;
|
||||
|
||||
/**
|
||||
* @return true if configuration is disabled by default
|
||||
* @return true if configuration is enabled by default
|
||||
*/
|
||||
boolean isDisabledByDefault();
|
||||
boolean isEnabledByDefault();
|
||||
|
||||
/**
|
||||
* @return true if configuration should be aborted
|
||||
|
|
|
@ -209,7 +209,7 @@ public class Configurations extends AbstractList<Configuration> implements Dumpa
|
|||
if (configurations == null)
|
||||
{
|
||||
configurations = new Configurations(Configurations.getKnown().stream()
|
||||
.filter(c -> !c.isDisabledByDefault())
|
||||
.filter(c -> c.isEnabledByDefault())
|
||||
.map(c -> c.getClass().getName())
|
||||
.toArray(String[]::new));
|
||||
}
|
||||
|
@ -279,6 +279,27 @@ public class Configurations extends AbstractList<Configuration> implements Dumpa
|
|||
}
|
||||
}
|
||||
|
||||
public <T> T get(Class<? extends T> configClass)
|
||||
{
|
||||
for (Configuration configuration : _configurations)
|
||||
{
|
||||
if (configClass.isAssignableFrom(configuration.getClass()))
|
||||
return (T)configuration;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> List<T> getConfigurations(Class<? extends T> configClass)
|
||||
{
|
||||
List<T> list = new ArrayList<>();
|
||||
for (Configuration configuration : _configurations)
|
||||
{
|
||||
if (configClass.isAssignableFrom(configuration.getClass()))
|
||||
list.add((T)configuration);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
_configurations.clear();
|
||||
|
|
|
@ -95,7 +95,7 @@ import org.eclipse.jetty.util.resource.ResourceCollection;
|
|||
* <ul>
|
||||
* <li>Add all Server class inclusions from all known configurations {@link Configurations#getKnown()}</li>
|
||||
* <li>{@link #loadConfigurations()}, which uses either explicitly set Configurations or takes the server
|
||||
* default (which is all known non {@link Configuration#isDisabledByDefault()} Configurations.</li>
|
||||
* default (which is all known {@link Configuration#isEnabledByDefault()} Configurations.</li>
|
||||
* <li>Sort the configurations using {@link TopologicalSort} in {@link Configurations#sort()}.</li>
|
||||
* <li>Add all Server class exclusions from this webapps {@link Configurations}</li>
|
||||
* <li>Add all System classes inclusions and exclusions for this webapps {@link Configurations}</li>
|
||||
|
@ -183,10 +183,10 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
"org.eclipse.jetty." // hide jetty classes
|
||||
);
|
||||
|
||||
private final Configurations _configurations = new Configurations();
|
||||
private final ClassMatcher _systemClasses = new ClassMatcher(__dftSystemClasses);
|
||||
private final ClassMatcher _serverClasses = new ClassMatcher(__dftServerClasses);
|
||||
|
||||
private Configurations _configurations;
|
||||
private String _defaultsDescriptor = WEB_DEFAULTS_XML;
|
||||
private String _descriptor = null;
|
||||
private final List<String> _overrideDescriptors = new ArrayList<>();
|
||||
|
@ -570,18 +570,21 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
// Prepare for configuration
|
||||
MultiException mx = new MultiException();
|
||||
for (Configuration configuration : _configurations)
|
||||
if (_configurations != null)
|
||||
{
|
||||
try
|
||||
for (Configuration configuration : _configurations)
|
||||
{
|
||||
configuration.destroy(this);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
mx.add(e);
|
||||
try
|
||||
{
|
||||
configuration.destroy(this);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
mx.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
_configurations.clear();
|
||||
_configurations = null;
|
||||
super.destroy();
|
||||
mx.ifExceptionThrowRuntime();
|
||||
}
|
||||
|
@ -615,10 +618,9 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
/**
|
||||
* @return Returns the configurations.
|
||||
*/
|
||||
public Configurations getWebAppConfigurations()
|
||||
public Configurations getConfigurations()
|
||||
{
|
||||
if (_configurations.size() == 0)
|
||||
loadConfigurations();
|
||||
loadConfigurations();
|
||||
return _configurations;
|
||||
}
|
||||
|
||||
|
@ -885,10 +887,18 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
protected void loadConfigurations()
|
||||
{
|
||||
//if the configuration instances have been set explicitly, use them
|
||||
if (!_configurations.isEmpty())
|
||||
if (_configurations != null)
|
||||
return;
|
||||
if (isStarted())
|
||||
throw new IllegalStateException();
|
||||
_configurations = newConfigurations();
|
||||
}
|
||||
|
||||
_configurations.add(Configurations.getServerDefault(getServer()).toArray());
|
||||
protected Configurations newConfigurations()
|
||||
{
|
||||
Configurations configurations = new Configurations();
|
||||
configurations.add(Configurations.getServerDefault(getServer()).toArray());
|
||||
return configurations;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -958,8 +968,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
*/
|
||||
public void setConfigurationClasses(String[] configurations)
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException();
|
||||
if (_configurations == null)
|
||||
_configurations = new Configurations();
|
||||
_configurations.set(configurations);
|
||||
}
|
||||
|
||||
|
@ -973,15 +983,13 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
*/
|
||||
public void setConfigurations(Configuration[] configurations)
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException();
|
||||
if (_configurations == null)
|
||||
_configurations = new Configurations();
|
||||
_configurations.set(configurations);
|
||||
}
|
||||
|
||||
public void addConfiguration(Configuration... configuration)
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException();
|
||||
loadConfigurations();
|
||||
_configurations.add(configuration);
|
||||
}
|
||||
|
@ -989,12 +997,19 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
public <T> T getConfiguration(Class<? extends T> configClass)
|
||||
{
|
||||
loadConfigurations();
|
||||
for (Configuration configuration : _configurations)
|
||||
{
|
||||
if (configClass.isAssignableFrom(configuration.getClass()))
|
||||
return (T)configuration;
|
||||
}
|
||||
return null;
|
||||
return _configurations.get(configClass);
|
||||
}
|
||||
|
||||
public void removeConfiguration(Configuration... configurations)
|
||||
{
|
||||
if (_configurations != null)
|
||||
_configurations.remove(configurations);
|
||||
}
|
||||
|
||||
public void removeConfiguration(Class<? extends Configuration>... configurations)
|
||||
{
|
||||
if (_configurations != null)
|
||||
_configurations.remove(configurations);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -100,7 +100,7 @@ public class WebAppContextTest
|
|||
{
|
||||
Configurations.cleanKnown();
|
||||
String[] known_and_enabled = Configurations.getKnown().stream()
|
||||
.filter(c -> !c.isDisabledByDefault())
|
||||
.filter(c -> c.isEnabledByDefault())
|
||||
.map(c -> c.getClass().getName())
|
||||
.toArray(String[]::new);
|
||||
|
||||
|
@ -108,7 +108,7 @@ public class WebAppContextTest
|
|||
|
||||
//test if no classnames set, its the defaults
|
||||
WebAppContext wac = new WebAppContext();
|
||||
assertThat(wac.getWebAppConfigurations().stream()
|
||||
assertThat(wac.getConfigurations().stream()
|
||||
.map(c -> c.getClass().getName())
|
||||
.collect(Collectors.toList()),
|
||||
Matchers.containsInAnyOrder(known_and_enabled));
|
||||
|
@ -126,7 +126,7 @@ public class WebAppContextTest
|
|||
Configurations.cleanKnown();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
wac.setServer(new Server());
|
||||
assertThat(wac.getWebAppConfigurations().stream().map(c -> c.getClass().getName()).collect(Collectors.toList()),
|
||||
assertThat(wac.getConfigurations().stream().map(c -> c.getClass().getName()).collect(Collectors.toList()),
|
||||
Matchers.contains(
|
||||
"org.eclipse.jetty.webapp.JmxConfiguration",
|
||||
"org.eclipse.jetty.webapp.WebInfConfiguration",
|
||||
|
@ -144,14 +144,14 @@ public class WebAppContextTest
|
|||
Configuration[] configs = {new WebInfConfiguration()};
|
||||
WebAppContext wac = new WebAppContext();
|
||||
wac.setConfigurations(configs);
|
||||
assertThat(wac.getWebAppConfigurations(), Matchers.contains(configs));
|
||||
assertThat(wac.getConfigurations(), Matchers.contains(configs));
|
||||
|
||||
//test that explicit config instances override any from server
|
||||
String[] classNames = {"x.y.z"};
|
||||
Server server = new Server();
|
||||
server.setAttribute(Configuration.ATTR, classNames);
|
||||
wac.setServer(server);
|
||||
assertThat(wac.getWebAppConfigurations(), Matchers.contains(configs));
|
||||
assertThat(wac.getConfigurations(), Matchers.contains(configs));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -29,6 +29,12 @@
|
|||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-javax-websocket-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-xml</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
|
@ -24,9 +24,11 @@ import javax.websocket.ClientEndpointConfig;
|
|||
import javax.websocket.WebSocketContainer;
|
||||
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
|
||||
import org.eclipse.jetty.io.ClientConnector;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.websocket.jsr356.ClientContainer;
|
||||
import org.eclipse.jetty.websocket.javax.client.JavaxWebSocketClientContainer;
|
||||
|
||||
public class SecureClientContainerExample
|
||||
{
|
||||
|
@ -73,11 +75,14 @@ public class SecureClientContainerExample
|
|||
*/
|
||||
public static WebSocketContainer getConfiguredWebSocketContainer() throws Exception
|
||||
{
|
||||
SslContextFactory ssl = new SslContextFactory.Client();
|
||||
SslContextFactory.Client ssl = new SslContextFactory.Client();
|
||||
ssl.setExcludeCipherSuites(); // echo.websocket.org use WEAK cipher suites
|
||||
HttpClient httpClient = new HttpClient(ssl);
|
||||
ClientContainer clientContainer = new ClientContainer(httpClient);
|
||||
clientContainer.getClient().addManaged(httpClient); // allow clientContainer to own httpClient (for start/stop lifecycle)
|
||||
ClientConnector clientConnector = new ClientConnector();
|
||||
clientConnector.setSslContextFactory(ssl);
|
||||
|
||||
HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
|
||||
JavaxWebSocketClientContainer clientContainer = new JavaxWebSocketClientContainer(httpClient);
|
||||
clientContainer.addManaged(httpClient); // allow clientContainer to own httpClient (for start/stop lifecycle)
|
||||
clientContainer.start();
|
||||
return clientContainer;
|
||||
}
|
|
@ -21,14 +21,12 @@ package examples;
|
|||
import java.io.FileNotFoundException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.websocket.ClientEndpointConfig;
|
||||
import javax.websocket.ContainerProvider;
|
||||
import javax.websocket.WebSocketContainer;
|
||||
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.thread.ThreadClassLoaderScope;
|
||||
|
||||
public class SecureWebSocketContainerExample
|
||||
{
|
||||
|
@ -69,47 +67,27 @@ public class SecureWebSocketContainerExample
|
|||
* Since javax.websocket does not have an API for configuring SSL, each implementation
|
||||
* of javax.websocket has to come up with their own SSL configuration mechanism.
|
||||
* <p>
|
||||
* When the call to {@link javax.websocket.ContainerProvider}.{@link ContainerProvider#getWebSocketContainer()}
|
||||
* occurs, that needs to have a started and available WebSocket Client.
|
||||
* Jetty's {@code WebSocketClient} must have a Jetty {@code HttpClient} started as well.
|
||||
* If you want SSL, then that configuration has to be passed into the Jetty {@code HttpClient} at initialization.
|
||||
* When the {@link WebSocketContainer} is used it will need to create and start a Jetty WebSocket Client.
|
||||
* The {@code WebSocketClient} must use a Jetty {@code HttpClient} which can be configured for SSL, this
|
||||
* configuration needs to be passed into the Jetty {@code HttpClient} at initialization.
|
||||
* </p>
|
||||
* <p>
|
||||
* How Jetty makes this available, is via the {@code jetty-websocket-httpclient.xml} classloader resource
|
||||
* along with the jetty-xml artifact.
|
||||
* </p>
|
||||
* <p>
|
||||
* This method will look for the file in the classloader resources, and then
|
||||
* sets up a {@link URLClassLoader} to make that {@code jetty-websocket-httpclient.xml} available
|
||||
* for this specific example.
|
||||
* If we had put the `jetty-websocket-httpclient.xml` in the root of a JAR file loaded by this
|
||||
* project then you can skip all of the classloader trickery this method performs.
|
||||
* </p>
|
||||
*
|
||||
* @return the client WebSocketContainer
|
||||
* @see <a href="https://github.com/eclipse-ee4j/websocket-api/issues/210">javax.websocket issue #210</a>
|
||||
*/
|
||||
public static WebSocketContainer getConfiguredWebSocketContainer() throws Exception
|
||||
{
|
||||
URL jettyHttpClientConfigUrl = Thread.currentThread().getContextClassLoader()
|
||||
.getResource("examples/jetty-websocket-httpclient.xml");
|
||||
.getResource("jetty-websocket-httpclient.xml");
|
||||
|
||||
if (jettyHttpClientConfigUrl == null)
|
||||
{
|
||||
throw new FileNotFoundException("Unable to find Jetty HttpClient configuration XML");
|
||||
}
|
||||
|
||||
URI jettyConfigDirUri = jettyHttpClientConfigUrl.toURI().resolve("./");
|
||||
|
||||
ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
URL[] urls = new URL[]{
|
||||
jettyConfigDirUri.toURL()
|
||||
};
|
||||
URLClassLoader classLoader = new URLClassLoader(urls, parentClassLoader);
|
||||
|
||||
try (ThreadClassLoaderScope ignore = new ThreadClassLoaderScope(classLoader))
|
||||
{
|
||||
return ContainerProvider.getWebSocketContainer();
|
||||
}
|
||||
return ContainerProvider.getWebSocketContainer();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.client.HttpClient">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.util.ssl.SslContextFactory$Client">
|
||||
<Set name="trustAll" type="java.lang.Boolean">false</Set>
|
||||
<Call name="addExcludeProtocols">
|
||||
<Arg>
|
||||
<Array type="java.lang.String">
|
||||
<Item>TLS/1.3</Item>
|
||||
</Array>
|
||||
</Arg>
|
||||
</Call>
|
||||
<Call name="setExcludeCipherSuites"><!-- websocket.org uses WEAK cipher suites -->
|
||||
<Arg>
|
||||
<Array type="java.lang.String" />
|
||||
</Arg>
|
||||
</Call>
|
||||
</New>
|
||||
</Arg>
|
||||
<Set name="connectTimeout">5000</Set>
|
||||
</Configure>
|
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
#
|
||||
# ========================================================================
|
||||
# Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
# ------------------------------------------------------------------------
|
||||
# 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.
|
||||
#
|
||||
# The Eclipse Public License is available at
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
# The Apache License v2.0 is available at
|
||||
# http://www.opensource.org/licenses/apache2.0.php
|
||||
#
|
||||
# You may elect to redistribute this code under either of these licenses.
|
||||
# ========================================================================
|
||||
#
|
||||
#
|
||||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
org.eclipse.jetty.LEVEL=INFO
|
||||
# org.eclipse.jetty.websocket.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.server.AbstractConnector.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.io.WriteFlusher.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.io.FillInterest.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.client.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.io.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.io.ManagedSelector.LEVEL=INFO
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.client.HttpClient">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.client.http.HttpClientTransportOverHTTP">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.io.ClientConnector">
|
||||
<Call name="setSslContextFactory">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.util.ssl.SslContextFactory$Client">
|
||||
<!-- websocket.org uses WEAK cipher suites -->
|
||||
<Set name="excludeCipherSuites">
|
||||
<Array type="java.lang.String"></Array>
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
</Arg>
|
||||
</Configure>
|
|
@ -50,6 +50,8 @@ public class FrameFlusher extends IteratingCallback
|
|||
private static final Logger LOG = Log.getLogger(FrameFlusher.class);
|
||||
private static final Throwable CLOSED_CHANNEL = new ClosedChannelException();
|
||||
|
||||
private final LongAdder messagesOut = new LongAdder();
|
||||
private final LongAdder bytesOut = new LongAdder();
|
||||
private final ByteBufferPool bufferPool;
|
||||
private final EndPoint endPoint;
|
||||
private final int bufferSize;
|
||||
|
@ -62,13 +64,12 @@ public class FrameFlusher extends IteratingCallback
|
|||
private final List<Entry> previousEntries;
|
||||
private final List<Entry> failedEntries;
|
||||
|
||||
private ByteBuffer batchBuffer = null;
|
||||
private ByteBuffer batchBuffer;
|
||||
private boolean canEnqueue = true;
|
||||
private boolean flushed = true;
|
||||
private Throwable closedCause;
|
||||
private LongAdder messagesOut = new LongAdder();
|
||||
private LongAdder bytesOut = new LongAdder();
|
||||
private long idleTimeout = 0;
|
||||
private long idleTimeout;
|
||||
private boolean useDirectByteBuffers;
|
||||
|
||||
public FrameFlusher(ByteBufferPool bufferPool, Scheduler scheduler, Generator generator, EndPoint endPoint, int bufferSize, int maxGather)
|
||||
{
|
||||
|
@ -84,6 +85,16 @@ public class FrameFlusher extends IteratingCallback
|
|||
this.timeoutScheduler = scheduler;
|
||||
}
|
||||
|
||||
public boolean isUseDirectByteBuffers()
|
||||
{
|
||||
return useDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseDirectByteBuffers(boolean useDirectByteBuffers)
|
||||
{
|
||||
this.useDirectByteBuffers = useDirectByteBuffers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue a Frame to be written to the endpoint.
|
||||
*
|
||||
|
@ -225,7 +236,7 @@ public class FrameFlusher extends IteratingCallback
|
|||
// Acquire a batchBuffer if we don't have one
|
||||
if (batchBuffer == null)
|
||||
{
|
||||
batchBuffer = bufferPool.acquire(bufferSize, true);
|
||||
batchBuffer = acquireBuffer(bufferSize);
|
||||
buffers.add(batchBuffer);
|
||||
}
|
||||
|
||||
|
@ -249,7 +260,10 @@ public class FrameFlusher extends IteratingCallback
|
|||
else
|
||||
{
|
||||
// Add headers and payload to the list of buffers
|
||||
buffers.add(entry.generateHeaderBytes());
|
||||
// TODO: release this buffer.
|
||||
ByteBuffer buffer = acquireBuffer(Generator.MAX_HEADER_LENGTH);
|
||||
buffers.add(buffer);
|
||||
entry.generateHeaderBytes(buffer);
|
||||
flush = true;
|
||||
ByteBuffer payload = entry.frame.getPayload();
|
||||
if (BufferUtil.hasContent(payload))
|
||||
|
@ -308,6 +322,11 @@ public class FrameFlusher extends IteratingCallback
|
|||
return Action.SCHEDULED;
|
||||
}
|
||||
|
||||
private ByteBuffer acquireBuffer(int capacity)
|
||||
{
|
||||
return bufferPool.acquire(capacity, isUseDirectByteBuffers());
|
||||
}
|
||||
|
||||
private int getQueueSize()
|
||||
{
|
||||
synchronized (this)
|
||||
|
@ -474,11 +493,6 @@ public class FrameFlusher extends IteratingCallback
|
|||
super(frame, callback, batch);
|
||||
}
|
||||
|
||||
private ByteBuffer generateHeaderBytes()
|
||||
{
|
||||
return headerBuffer = generator.generateHeaderBytes(frame);
|
||||
}
|
||||
|
||||
private void generateHeaderBytes(ByteBuffer buffer)
|
||||
{
|
||||
int pos = BufferUtil.flipToFill(buffer);
|
||||
|
|
|
@ -68,6 +68,8 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
|
|||
|
||||
// Read / Parse variables
|
||||
private RetainableByteBuffer networkBuffer;
|
||||
private boolean useInputDirectByteBuffers;
|
||||
private boolean useOutputDirectByteBuffers;
|
||||
|
||||
/**
|
||||
* Create a WSConnection.
|
||||
|
@ -132,6 +134,26 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
|
|||
return getEndPoint().getRemoteAddress();
|
||||
}
|
||||
|
||||
public boolean isUseInputDirectByteBuffers()
|
||||
{
|
||||
return useInputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseInputDirectByteBuffers(boolean useInputDirectByteBuffers)
|
||||
{
|
||||
this.useInputDirectByteBuffers = useInputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public boolean isUseOutputDirectByteBuffers()
|
||||
{
|
||||
return useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseOutputDirectByteBuffers(boolean useOutputDirectByteBuffers)
|
||||
{
|
||||
this.useOutputDirectByteBuffers = useOutputDirectByteBuffers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Physical connection disconnect.
|
||||
* <p>
|
||||
|
@ -222,7 +244,7 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
|
|||
synchronized (this)
|
||||
{
|
||||
if (networkBuffer == null)
|
||||
networkBuffer = new RetainableByteBuffer(bufferPool, getInputBufferSize());
|
||||
networkBuffer = newNetworkBuffer(getInputBufferSize());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,10 +259,15 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
|
|||
throw new IllegalStateException();
|
||||
|
||||
networkBuffer.release();
|
||||
networkBuffer = new RetainableByteBuffer(bufferPool, getInputBufferSize());
|
||||
networkBuffer = newNetworkBuffer(getInputBufferSize());
|
||||
}
|
||||
}
|
||||
|
||||
private RetainableByteBuffer newNetworkBuffer(int capacity)
|
||||
{
|
||||
return new RetainableByteBuffer(bufferPool, capacity, isUseInputDirectByteBuffers());
|
||||
}
|
||||
|
||||
private void releaseNetworkBuffer()
|
||||
{
|
||||
synchronized (this)
|
||||
|
@ -445,7 +472,7 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
|
|||
{
|
||||
synchronized (this)
|
||||
{
|
||||
networkBuffer = new RetainableByteBuffer(bufferPool, prefilled.remaining());
|
||||
networkBuffer = newNetworkBuffer(prefilled.remaining());
|
||||
}
|
||||
ByteBuffer buffer = networkBuffer.getBuffer();
|
||||
BufferUtil.clearToFill(buffer);
|
||||
|
@ -572,6 +599,7 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
|
|||
private Flusher(Scheduler scheduler, int bufferSize, Generator generator, EndPoint endpoint)
|
||||
{
|
||||
super(bufferPool, scheduler, generator, endpoint, bufferSize, 8);
|
||||
setUseDirectByteBuffers(isUseOutputDirectByteBuffers());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -201,6 +201,11 @@ public final class RFC6455Handshaker implements Handshaker
|
|||
|
||||
// Create a connection
|
||||
WebSocketConnection connection = newWebSocketConnection(httpChannel.getEndPoint(), connector.getExecutor(), connector.getScheduler(), connector.getByteBufferPool(), coreSession);
|
||||
// TODO: perhaps use of direct buffers should be WebSocket specific
|
||||
// rather than inheriting the setting from HttpConfiguration.
|
||||
HttpConfiguration httpConfig = httpChannel.getHttpConfiguration();
|
||||
connection.setUseInputDirectByteBuffers(httpConfig.isUseInputDirectByteBuffers());
|
||||
connection.setUseOutputDirectByteBuffers(httpChannel.isUseOutputDirectByteBuffers());
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("connection {}", connection);
|
||||
if (connection == null)
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.websocket.core.CloseStatus;
|
||||
import org.eclipse.jetty.websocket.core.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
|
@ -88,7 +89,7 @@ public class ValidationExtensionTest extends WebSocketTester
|
|||
Frame frame = serverHandler.receivedFrames.poll(5, TimeUnit.SECONDS);
|
||||
assertNotNull(frame);
|
||||
assertThat(frame.getOpCode(), is(OpCode.BINARY));
|
||||
assertThat(frame.getPayload().array(), is(nonUtf8Payload));
|
||||
assertThat(BufferUtil.toArray(frame.getPayload()), is(nonUtf8Payload));
|
||||
|
||||
//close normally
|
||||
client.getOutputStream().write(RawFrameBuilder.buildClose(CloseStatus.NORMAL_STATUS, true));
|
||||
|
@ -113,13 +114,13 @@ public class ValidationExtensionTest extends WebSocketTester
|
|||
Frame frame = serverHandler.receivedFrames.poll(5, TimeUnit.SECONDS);
|
||||
assertNotNull(frame);
|
||||
assertThat(frame.getOpCode(), is(OpCode.TEXT));
|
||||
assertThat(frame.getPayload().array(), is(initialPayload));
|
||||
assertThat(BufferUtil.toArray(frame.getPayload()), is(initialPayload));
|
||||
|
||||
client.getOutputStream().write(RawFrameBuilder.buildFrame(OpCode.CONTINUATION, continuationPayload, true));
|
||||
frame = serverHandler.receivedFrames.poll(5, TimeUnit.SECONDS);
|
||||
assertNotNull(frame);
|
||||
assertThat(frame.getOpCode(), is(OpCode.CONTINUATION));
|
||||
assertThat(frame.getPayload().array(), is(continuationPayload));
|
||||
assertThat(BufferUtil.toArray(frame.getPayload()), is(continuationPayload));
|
||||
|
||||
//close normally
|
||||
client.getOutputStream().write(RawFrameBuilder.buildClose(CloseStatus.NORMAL_STATUS, true));
|
||||
|
@ -144,7 +145,7 @@ public class ValidationExtensionTest extends WebSocketTester
|
|||
Frame frame = serverHandler.receivedFrames.poll(5, TimeUnit.SECONDS);
|
||||
assertNotNull(frame);
|
||||
assertThat(frame.getOpCode(), is(OpCode.TEXT));
|
||||
assertThat(frame.getPayload().array(), is(initialPayload));
|
||||
assertThat(BufferUtil.toArray(frame.getPayload()), is(initialPayload));
|
||||
|
||||
client.getOutputStream().write(RawFrameBuilder.buildFrame(OpCode.CONTINUATION, incompleteContinuationPayload, true));
|
||||
frame = receiveFrame(client.getInputStream());
|
||||
|
|
|
@ -164,12 +164,6 @@ public class MockEndpoint implements EndPoint
|
|||
throw new UnsupportedOperationException(NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedForDirectBuffers()
|
||||
{
|
||||
throw new UnsupportedOperationException(NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgrade(Connection newConnection)
|
||||
{
|
||||
|
|
|
@ -24,7 +24,6 @@ import java.util.concurrent.BlockingQueue;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.BlockingArrayQueue;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
@ -43,8 +42,6 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
@ -207,29 +204,6 @@ public class WebSocketServerTest extends WebSocketTester
|
|||
}
|
||||
assertThat(serverHandler.receivedFrames.size(), is(5));
|
||||
assertThat(receivedCallbacks.size(), is(5));
|
||||
|
||||
byte[] first = serverHandler.receivedFrames.poll().getPayload().array();
|
||||
assertThat(serverHandler.receivedFrames.poll().getPayload().array(), sameInstance(first));
|
||||
assertThat(serverHandler.receivedFrames.poll().getPayload().array(), sameInstance(first));
|
||||
byte[] second = serverHandler.receivedFrames.poll().getPayload().array();
|
||||
assertThat(serverHandler.receivedFrames.poll().getPayload().array(), sameInstance(second));
|
||||
assertThat(first, not(sameInstance(second)));
|
||||
|
||||
ByteBufferPool pool = server.getServer().getConnectors()[0].getByteBufferPool();
|
||||
|
||||
assertThat(pool.acquire(first.length, false).array(), not(sameInstance(first)));
|
||||
receivedCallbacks.poll().succeeded();
|
||||
assertThat(pool.acquire(first.length, false).array(), not(sameInstance(first)));
|
||||
receivedCallbacks.poll().succeeded();
|
||||
assertThat(pool.acquire(first.length, false).array(), not(sameInstance(first)));
|
||||
receivedCallbacks.poll().succeeded();
|
||||
assertThat(pool.acquire(first.length, false).array(), sameInstance(first));
|
||||
|
||||
assertThat(pool.acquire(second.length, false).array(), not(sameInstance(second)));
|
||||
receivedCallbacks.poll().succeeded();
|
||||
assertThat(pool.acquire(second.length, false).array(), not(sameInstance(second)));
|
||||
receivedCallbacks.poll().succeeded();
|
||||
assertThat(pool.acquire(second.length, false).array(), sameInstance(second));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1146,6 +1146,7 @@ public class XmlConfigurationTest
|
|||
|
||||
ByteArrayOutputStream logBytes = null;
|
||||
Logger logger = Log.getLogger(XmlConfiguration.class);
|
||||
logger.setDebugEnabled(true);
|
||||
if (logger instanceof StdErrLog)
|
||||
{
|
||||
StdErrLog stdErrLog = (StdErrLog)logger;
|
||||
|
@ -1155,6 +1156,7 @@ public class XmlConfigurationTest
|
|||
|
||||
xmlConfiguration.configure();
|
||||
|
||||
logger.setDebugEnabled(false);
|
||||
if (logBytes != null)
|
||||
{
|
||||
String[] lines = logBytes.toString(UTF_8.name()).split(System.lineSeparator());
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -272,7 +272,7 @@
|
|||
<configuration>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
<useReleaseProfile>false</useReleaseProfile>
|
||||
<goals>javadoc:aggregate-jar deploy</goals>
|
||||
<goals>deploy</goals>
|
||||
<arguments>-Peclipse-release</arguments>
|
||||
<preparationGoals>clean install</preparationGoals>
|
||||
<mavenExecutorId>forked-path</mavenExecutorId>
|
||||
|
|
|
@ -142,4 +142,32 @@ public class DemoBaseTests extends AbstractDistributionTest
|
|||
assertThat(response.getContentAsString(), not(containsString("<span class=\"fail\">FAIL</span>")));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJPMS() throws Exception
|
||||
{
|
||||
String jettyVersion = System.getProperty("jettyVersion");
|
||||
DistributionTester distribution = DistributionTester.Builder.newInstance()
|
||||
.jettyVersion(jettyVersion)
|
||||
.jettyBase(Paths.get("demo-base"))
|
||||
.mavenLocalRepository(System.getProperty("mavenRepoPath"))
|
||||
.build();
|
||||
|
||||
int httpPort = distribution.freePort();
|
||||
int httpsPort = distribution.freePort();
|
||||
String[] args = {
|
||||
"--jpms",
|
||||
"jetty.http.port=" + httpPort,
|
||||
"jetty.httpConfig.port=" + httpsPort,
|
||||
"jetty.ssl.port=" + httpsPort
|
||||
};
|
||||
try (DistributionTester.Run run = distribution.start(args))
|
||||
{
|
||||
assertTrue(run.awaitConsoleLogsFor("Started Server@", 10, TimeUnit.SECONDS));
|
||||
|
||||
startHttpClient();
|
||||
ContentResponse response = client.GET("http://localhost:" + httpPort + "/test/hello");
|
||||
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -193,7 +193,7 @@ public class DeploymentErrorTest
|
|||
assertThat("ContextHandler.isAvailable", context.isAvailable(), is(false));
|
||||
WebAppContext webapp = (WebAppContext)context;
|
||||
TrackedConfiguration trackedConfiguration = null;
|
||||
for (Configuration webappConfig : webapp.getWebAppConfigurations())
|
||||
for (Configuration webappConfig : webapp.getConfigurations())
|
||||
{
|
||||
if (webappConfig instanceof TrackedConfiguration)
|
||||
trackedConfiguration = (TrackedConfiguration)webappConfig;
|
||||
|
@ -239,7 +239,7 @@ public class DeploymentErrorTest
|
|||
assertThat("ContextHandler.isAvailable", context.isAvailable(), is(false));
|
||||
WebAppContext webapp = (WebAppContext)context;
|
||||
TrackedConfiguration trackedConfiguration = null;
|
||||
for (Configuration webappConfig : webapp.getWebAppConfigurations())
|
||||
for (Configuration webappConfig : webapp.getConfigurations())
|
||||
{
|
||||
if (webappConfig instanceof TrackedConfiguration)
|
||||
trackedConfiguration = (TrackedConfiguration)webappConfig;
|
||||
|
@ -285,7 +285,7 @@ public class DeploymentErrorTest
|
|||
assertThat("ContextHandler.isAvailable", context.isAvailable(), is(false));
|
||||
WebAppContext webapp = (WebAppContext)context;
|
||||
TrackedConfiguration trackedConfiguration = null;
|
||||
for (Configuration webappConfig : webapp.getWebAppConfigurations())
|
||||
for (Configuration webappConfig : webapp.getConfigurations())
|
||||
{
|
||||
if (webappConfig instanceof TrackedConfiguration)
|
||||
trackedConfiguration = (TrackedConfiguration)webappConfig;
|
||||
|
|
|
@ -28,3 +28,5 @@ org.eclipse.jetty.websocket.jsr356=false
|
|||
# Create and configure the test realm
|
||||
jetty.demo.realm=etc/realm.properties
|
||||
|
||||
# JDBC needed by test-jndi and test-spec
|
||||
--module=jdbc
|
||||
|
|
Loading…
Reference in New Issue