Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-10.0.x-5133-webappcontext-extraclasspath-cleanup
This commit is contained in:
commit
f881a1a2fe
|
@ -0,0 +1,10 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "maven"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
|
@ -647,7 +647,7 @@ public class HttpClient extends ContainerLifeCycle
|
|||
}
|
||||
|
||||
/**
|
||||
* @return the max time, in milliseconds, a connection can take to connect to destinations
|
||||
* @return the max time, in milliseconds, a connection can take to connect to destinations. Zero value means infinite timeout.
|
||||
*/
|
||||
@ManagedAttribute("The timeout, in milliseconds, for connect() operations")
|
||||
public long getConnectTimeout()
|
||||
|
@ -656,7 +656,7 @@ public class HttpClient extends ContainerLifeCycle
|
|||
}
|
||||
|
||||
/**
|
||||
* @param connectTimeout the max time, in milliseconds, a connection can take to connect to destinations
|
||||
* @param connectTimeout the max time, in milliseconds, a connection can take to connect to destinations. Zero value means infinite timeout.
|
||||
* @see java.net.Socket#connect(SocketAddress, int)
|
||||
*/
|
||||
public void setConnectTimeout(long connectTimeout)
|
||||
|
|
|
@ -40,7 +40,6 @@ public class HttpChannelOverHTTP extends HttpChannel
|
|||
private final HttpConnectionOverHTTP connection;
|
||||
private final HttpSenderOverHTTP sender;
|
||||
private final HttpReceiverOverHTTP receiver;
|
||||
private final LongAdder inMessages = new LongAdder();
|
||||
private final LongAdder outMessages = new LongAdder();
|
||||
|
||||
public HttpChannelOverHTTP(HttpConnectionOverHTTP connection)
|
||||
|
@ -93,7 +92,6 @@ public class HttpChannelOverHTTP extends HttpChannel
|
|||
|
||||
public void receive()
|
||||
{
|
||||
inMessages.increment();
|
||||
receiver.receive();
|
||||
}
|
||||
|
||||
|
@ -149,7 +147,7 @@ public class HttpChannelOverHTTP extends HttpChannel
|
|||
|
||||
protected long getMessagesIn()
|
||||
{
|
||||
return inMessages.longValue();
|
||||
return receiver.getMessagesIn();
|
||||
}
|
||||
|
||||
protected long getMessagesOut()
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.client.http;
|
|||
|
||||
import java.io.EOFException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.HttpClientTransport;
|
||||
|
@ -45,6 +46,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HttpReceiverOverHTTP.class);
|
||||
|
||||
private final LongAdder inMessages = new LongAdder();
|
||||
private final HttpParser parser;
|
||||
private RetainableByteBuffer networkBuffer;
|
||||
private boolean shutdown;
|
||||
|
@ -343,9 +345,11 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
return false;
|
||||
|
||||
int status = exchange.getResponse().getStatus();
|
||||
|
||||
if (status != HttpStatus.CONTINUE_100)
|
||||
{
|
||||
inMessages.increment();
|
||||
complete = true;
|
||||
}
|
||||
|
||||
return !responseSuccess(exchange);
|
||||
}
|
||||
|
@ -386,6 +390,11 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
getHttpConnection().close(failure);
|
||||
}
|
||||
|
||||
long getMessagesIn()
|
||||
{
|
||||
return inMessages.longValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
|
|
@ -396,6 +396,38 @@ public class ConnectionPoolTest
|
|||
assertEquals(0, connectionPool.getConnectionCount());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("pools")
|
||||
public void testIdleTimeoutNoRequests(ConnectionPoolFactory factory) throws Exception
|
||||
{
|
||||
startServer(new EmptyServerHandler());
|
||||
startClient(destination ->
|
||||
{
|
||||
try
|
||||
{
|
||||
ConnectionPool connectionPool = factory.factory.newConnectionPool(destination);
|
||||
connectionPool.preCreateConnections(1).get();
|
||||
return connectionPool;
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
});
|
||||
long idleTimeout = 1000;
|
||||
client.setIdleTimeout(idleTimeout);
|
||||
|
||||
// Trigger the creation of a destination, that will create the connection pool.
|
||||
HttpDestination destination = client.resolveDestination(new Origin("http", "localhost", connector.getLocalPort()));
|
||||
AbstractConnectionPool connectionPool = (AbstractConnectionPool)destination.getConnectionPool();
|
||||
assertEquals(1, connectionPool.getConnectionCount());
|
||||
|
||||
// Wait for the pre-created connections to idle timeout.
|
||||
Thread.sleep(idleTimeout + idleTimeout / 2);
|
||||
|
||||
assertEquals(0, connectionPool.getConnectionCount());
|
||||
}
|
||||
|
||||
private static class ConnectionPoolFactory
|
||||
{
|
||||
private final String name;
|
||||
|
|
|
@ -796,7 +796,7 @@ public interface HttpFields extends Iterable<HttpField>
|
|||
{
|
||||
if (_size == 0)
|
||||
throw new IllegalStateException();
|
||||
Mutable.this.remove(_index - 1);
|
||||
Mutable.this.remove(--_index);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1059,7 +1059,7 @@ public interface HttpFields extends Iterable<HttpField>
|
|||
}
|
||||
// Remember and remove additional fields
|
||||
found.add(f);
|
||||
remove(i);
|
||||
remove(i--);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1088,7 +1088,7 @@ public interface HttpFields extends Iterable<HttpField>
|
|||
{
|
||||
HttpField f = _fields[i];
|
||||
if (f.getHeader() == name)
|
||||
remove(i);
|
||||
remove(i--);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -1099,7 +1099,7 @@ public interface HttpFields extends Iterable<HttpField>
|
|||
{
|
||||
HttpField f = _fields[i];
|
||||
if (fields.contains(f.getHeader()))
|
||||
remove(i);
|
||||
remove(i--);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -1116,7 +1116,7 @@ public interface HttpFields extends Iterable<HttpField>
|
|||
{
|
||||
HttpField f = _fields[i];
|
||||
if (f.is(name))
|
||||
remove(i);
|
||||
remove(i--);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -912,11 +912,12 @@ public class HttpFieldsTest
|
|||
fields.add(new HttpField("After", "value"));
|
||||
assertThat(fields.stream().map(HttpField::toString).collect(Collectors.toList()), contains("Before: value", "Test: one", "After: value"));
|
||||
|
||||
fields.add(new HttpField("Test", "extra"));
|
||||
assertThat(fields.stream().map(HttpField::toString).collect(Collectors.toList()), contains("Before: value", "Test: one", "After: value", "Test: extra"));
|
||||
fields.add(new HttpField("Test", "two"));
|
||||
fields.add(new HttpField("Test", "three"));
|
||||
assertThat(fields.stream().map(HttpField::toString).collect(Collectors.toList()), contains("Before: value", "Test: one", "After: value", "Test: two", "Test: three"));
|
||||
|
||||
fields.computeField("Test", (n, f) -> new HttpField("TEST", "count=" + f.size()));
|
||||
assertThat(fields.stream().map(HttpField::toString).collect(Collectors.toList()), contains("Before: value", "TEST: count=2", "After: value"));
|
||||
assertThat(fields.stream().map(HttpField::toString).collect(Collectors.toList()), contains("Before: value", "TEST: count=3", "After: value"));
|
||||
|
||||
fields.computeField("TEST", (n, f) -> null);
|
||||
assertThat(fields.stream().map(HttpField::toString).collect(Collectors.toList()), contains("Before: value", "After: value"));
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.io;
|
||||
|
||||
import java.util.AbstractSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.eclipse.jetty.util.IncludeExcludeSet;
|
||||
|
||||
public class IncludeExcludeConnectionStatistics extends ConnectionStatistics
|
||||
{
|
||||
private final IncludeExcludeSet<Class<? extends Connection>, Connection> _set = new IncludeExcludeSet<>(ConnectionSet.class);
|
||||
|
||||
public void include(String className) throws ClassNotFoundException
|
||||
{
|
||||
_set.include(connectionForName(className));
|
||||
}
|
||||
|
||||
public void include(Class<? extends Connection> clazz)
|
||||
{
|
||||
_set.include(clazz);
|
||||
}
|
||||
|
||||
public void exclude(String className) throws ClassNotFoundException
|
||||
{
|
||||
_set.exclude(connectionForName(className));
|
||||
}
|
||||
|
||||
public void exclude(Class<? extends Connection> clazz)
|
||||
{
|
||||
_set.exclude(clazz);
|
||||
}
|
||||
|
||||
private Class<? extends Connection> connectionForName(String className) throws ClassNotFoundException
|
||||
{
|
||||
Class<?> aClass = Class.forName(className);
|
||||
if (!Connection.class.isAssignableFrom(aClass))
|
||||
throw new IllegalArgumentException("Class is not a Connection");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends Connection> connectionClass = (Class<? extends Connection>)aClass;
|
||||
return connectionClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpened(Connection connection)
|
||||
{
|
||||
if (_set.test(connection))
|
||||
super.onOpened(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosed(Connection connection)
|
||||
{
|
||||
if (_set.test(connection))
|
||||
super.onClosed(connection);
|
||||
}
|
||||
|
||||
public static class ConnectionSet extends AbstractSet<Class<? extends Connection>> implements Predicate<Connection>
|
||||
{
|
||||
private final Set<Class<? extends Connection>> set = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public boolean add(Class<? extends Connection> aClass)
|
||||
{
|
||||
return set.add(aClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o)
|
||||
{
|
||||
return set.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Class<? extends Connection>> iterator()
|
||||
{
|
||||
return set.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return set.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Connection connection)
|
||||
{
|
||||
if (connection == null)
|
||||
return false;
|
||||
return set.stream().anyMatch(c -> c.isAssignableFrom(connection.getClass()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -889,7 +889,11 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
|
|||
{
|
||||
this.channel = channel;
|
||||
this.attachment = attachment;
|
||||
this.timeout = ManagedSelector.this._selectorManager.getScheduler().schedule(this, ManagedSelector.this._selectorManager.getConnectTimeout(), TimeUnit.MILLISECONDS);
|
||||
long timeout = ManagedSelector.this._selectorManager.getConnectTimeout();
|
||||
if (timeout > 0)
|
||||
this.timeout = ManagedSelector.this._selectorManager.getScheduler().schedule(this, timeout, TimeUnit.MILLISECONDS);
|
||||
else
|
||||
this.timeout = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -920,7 +924,8 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
|
|||
{
|
||||
if (failed.compareAndSet(false, true))
|
||||
{
|
||||
timeout.cancel();
|
||||
if (timeout != null)
|
||||
timeout.cancel();
|
||||
IO.close(channel);
|
||||
ManagedSelector.this._selectorManager.connectionFailed(channel, failure, attachment);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
<version>2.13.2</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -18,19 +18,20 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.javax.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.Session;
|
||||
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.eclipse.jetty.util.component.Graceful;
|
||||
|
||||
public class SessionTracker extends AbstractLifeCycle implements JavaxWebSocketSessionListener, Graceful
|
||||
public class SessionTracker extends AbstractLifeCycle implements JavaxWebSocketSessionListener, Graceful, Dumpable
|
||||
{
|
||||
private final Set<JavaxWebSocketSession> sessions = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
private boolean isShutdown = false;
|
||||
|
@ -88,4 +89,16 @@ public class SessionTracker extends AbstractLifeCycle implements JavaxWebSocketS
|
|||
{
|
||||
return isShutdown;
|
||||
}
|
||||
|
||||
@ManagedAttribute("Total number of active WebSocket Sessions")
|
||||
public int getNumSessions()
|
||||
{
|
||||
return sessions.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
Dumpable.dumpObjects(out, indent, this, sessions);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>
|
||||
@{argLine} ${jetty.surefire.argLine} --add-exports org.eclipse.jetty.websocket.javax.server/org.eclipse.jetty.websocket.javax.server.examples=org.eclipse.jetty.websocket.javax.common --add-reads org.eclipse.jetty.websocket.javax.server=org.eclipse.jetty.security --add-reads org.eclipse.jetty.websocket.javax.common=org.eclipse.jetty.websocket.javax.server
|
||||
@{argLine} ${jetty.surefire.argLine} --add-reads org.eclipse.jetty.websocket.javax.server=org.eclipse.jetty.security --add-reads org.eclipse.jetty.websocket.javax.common=org.eclipse.jetty.websocket.javax.server
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.javax.server.examples;
|
||||
package org.eclipse.jetty.websocket.javax.tests.server.examples;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.websocket.HandshakeResponse;
|
|
@ -16,7 +16,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.javax.server.examples;
|
||||
package org.eclipse.jetty.websocket.javax.tests.server.examples;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpSession;
|
|
@ -16,7 +16,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.javax.server.examples;
|
||||
package org.eclipse.jetty.websocket.javax.tests.server.examples;
|
||||
|
||||
import java.security.Principal;
|
||||
import javax.websocket.HandshakeResponse;
|
|
@ -16,7 +16,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.javax.server.examples;
|
||||
package org.eclipse.jetty.websocket.javax.tests.server.examples;
|
||||
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.server.ServerEndpoint;
|
|
@ -16,7 +16,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.javax.server.examples;
|
||||
package org.eclipse.jetty.websocket.javax.tests.server.examples;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
|
@ -16,7 +16,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.javax.server.examples;
|
||||
package org.eclipse.jetty.websocket.javax.tests.server.examples;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
|
@ -18,22 +18,22 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.eclipse.jetty.util.component.Graceful;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketSessionListener;
|
||||
|
||||
public class SessionTracker extends AbstractLifeCycle implements WebSocketSessionListener, Graceful
|
||||
public class SessionTracker extends AbstractLifeCycle implements WebSocketSessionListener, Graceful, Dumpable
|
||||
{
|
||||
private final Set<Session> sessions = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
private boolean isShutdown = false;
|
||||
|
@ -91,4 +91,16 @@ public class SessionTracker extends AbstractLifeCycle implements WebSocketSessio
|
|||
{
|
||||
return isShutdown;
|
||||
}
|
||||
|
||||
@ManagedAttribute("Total number of active WebSocket Sessions")
|
||||
public int getNumSessions()
|
||||
{
|
||||
return sessions.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
Dumpable.dumpObjects(out, indent, this, sessions);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,6 +73,12 @@
|
|||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jmx</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.tests;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
@ -25,8 +26,8 @@ import java.util.concurrent.CountDownLatch;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.ConnectionStatistics;
|
||||
import org.eclipse.jetty.server.HttpConnection;
|
||||
import org.eclipse.jetty.io.IncludeExcludeConnectionStatistics;
|
||||
import org.eclipse.jetty.jmx.MBeanContainer;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
|
@ -38,8 +39,6 @@ import org.eclipse.jetty.websocket.core.Frame;
|
|||
import org.eclipse.jetty.websocket.core.OpCode;
|
||||
import org.eclipse.jetty.websocket.core.internal.Generator;
|
||||
import org.eclipse.jetty.websocket.core.internal.WebSocketConnection;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServletFactory;
|
||||
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
@ -51,52 +50,50 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
|
||||
public class WebSocketStatsTest
|
||||
{
|
||||
public static class MyWebSocketServlet extends JettyWebSocketServlet
|
||||
{
|
||||
@Override
|
||||
public void configure(JettyWebSocketServletFactory factory)
|
||||
{
|
||||
factory.setAutoFragment(false);
|
||||
factory.addMapping("/", (req, resp) -> new EchoSocket());
|
||||
}
|
||||
}
|
||||
|
||||
private final CountDownLatch wsConnectionClosed = new CountDownLatch(1);
|
||||
private Server server;
|
||||
private ServerConnector connector;
|
||||
private WebSocketClient client;
|
||||
private ConnectionStatistics statistics;
|
||||
private final CountDownLatch wsUpgradeComplete = new CountDownLatch(1);
|
||||
private final CountDownLatch wsConnectionClosed = new CountDownLatch(1);
|
||||
private IncludeExcludeConnectionStatistics statistics;
|
||||
|
||||
@BeforeEach
|
||||
public void start() throws Exception
|
||||
{
|
||||
statistics = new ConnectionStatistics()
|
||||
statistics = new IncludeExcludeConnectionStatistics();
|
||||
statistics.include(WebSocketConnection.class);
|
||||
|
||||
Connection.Listener.Adapter wsCloseListener = new Connection.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onClosed(Connection connection)
|
||||
{
|
||||
super.onClosed(connection);
|
||||
|
||||
if (connection instanceof WebSocketConnection)
|
||||
wsConnectionClosed.countDown();
|
||||
else if (connection instanceof HttpConnection)
|
||||
wsUpgradeComplete.countDown();
|
||||
}
|
||||
};
|
||||
|
||||
server = new Server();
|
||||
connector = new ServerConnector(server);
|
||||
connector.addBean(statistics);
|
||||
connector.addBean(wsCloseListener);
|
||||
server.addConnector(connector);
|
||||
|
||||
ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
contextHandler.setContextPath("/");
|
||||
contextHandler.addServlet(MyWebSocketServlet.class, "/testPath");
|
||||
server.setHandler(contextHandler);
|
||||
contextHandler.setContextPath("/");
|
||||
JettyWebSocketServletContainerInitializer.configure(contextHandler, (context, container) ->
|
||||
{
|
||||
container.setAutoFragment(false);
|
||||
container.addMapping("/", EchoSocket.class);
|
||||
});
|
||||
|
||||
JettyWebSocketServletContainerInitializer.configure(contextHandler, null);
|
||||
client = new WebSocketClient();
|
||||
client.setAutoFragment(false);
|
||||
|
||||
// Setup JMX.
|
||||
MBeanContainer mbeanContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
|
||||
server.addBean(mbeanContainer);
|
||||
|
||||
server.start();
|
||||
client.start();
|
||||
|
@ -105,8 +102,8 @@ public class WebSocketStatsTest
|
|||
@AfterEach
|
||||
public void stop() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
server.stop();
|
||||
client.stop();
|
||||
}
|
||||
|
||||
long getFrameByteSize(Frame frame)
|
||||
|
@ -120,22 +117,14 @@ public class WebSocketStatsTest
|
|||
@Test
|
||||
public void echoStatsTest() throws Exception
|
||||
{
|
||||
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/testPath");
|
||||
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/");
|
||||
EventSocket socket = new EventSocket();
|
||||
CompletableFuture<Session> connect = client.connect(socket, uri);
|
||||
|
||||
final long numMessages = 1000;
|
||||
final String msgText = "hello world";
|
||||
|
||||
long upgradeSentBytes;
|
||||
long upgradeReceivedBytes;
|
||||
|
||||
try (Session session = connect.get(5, TimeUnit.SECONDS))
|
||||
{
|
||||
wsUpgradeComplete.await(5, TimeUnit.SECONDS);
|
||||
upgradeSentBytes = statistics.getSentBytes();
|
||||
upgradeReceivedBytes = statistics.getReceivedBytes();
|
||||
|
||||
for (int i = 0; i < numMessages; i++)
|
||||
{
|
||||
session.getRemote().sendString(msgText);
|
||||
|
@ -147,18 +136,18 @@ public class WebSocketStatsTest
|
|||
assertThat(statistics.getConnectionsMax(), is(1L));
|
||||
assertThat(statistics.getConnections(), is(0L));
|
||||
|
||||
assertThat(statistics.getSentMessages(), is(numMessages + 2L));
|
||||
assertThat(statistics.getReceivedMessages(), is(numMessages + 2L));
|
||||
// Sent and r eceived all of the echo messages + 1 for the close frame.
|
||||
assertThat(statistics.getSentMessages(), is(numMessages + 1L));
|
||||
assertThat(statistics.getReceivedMessages(), is(numMessages + 1L));
|
||||
|
||||
Frame textFrame = new Frame(OpCode.TEXT, msgText);
|
||||
Frame closeFrame = CloseStatus.NORMAL_STATUS.toFrame();
|
||||
|
||||
final long textFrameSize = getFrameByteSize(textFrame);
|
||||
final long closeFrameSize = getFrameByteSize(closeFrame);
|
||||
final int maskSize = 4; // We use 4 byte mask for client frames in WSConnection
|
||||
|
||||
final long expectedSent = upgradeSentBytes + numMessages * textFrameSize + closeFrameSize;
|
||||
final long expectedReceived = upgradeReceivedBytes + numMessages * (textFrameSize + maskSize) + closeFrameSize + maskSize;
|
||||
final long expectedSent = numMessages * textFrameSize + closeFrameSize;
|
||||
final long expectedReceived = numMessages * (textFrameSize + maskSize) + (closeFrameSize + maskSize);
|
||||
|
||||
assertThat(statistics.getSentBytes(), is(expectedSent));
|
||||
assertThat(statistics.getReceivedBytes(), is(expectedReceived));
|
||||
|
|
|
@ -26,6 +26,9 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class InvokerUtils
|
||||
{
|
||||
public static class Arg
|
||||
|
@ -135,6 +138,7 @@ public class InvokerUtils
|
|||
}
|
||||
|
||||
public static final ParamIdentifier PARAM_IDENTITY = new ParamIdentity();
|
||||
private static final Logger LOG = LoggerFactory.getLogger(InvokerUtils.class);
|
||||
|
||||
/**
|
||||
* Bind optional arguments to provided method handle
|
||||
|
@ -425,6 +429,8 @@ public class InvokerUtils
|
|||
{
|
||||
if (!throwOnFailure)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Unable to obtain MethodHandle for " + method, e);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
14
pom.xml
14
pom.xml
|
@ -44,15 +44,15 @@
|
|||
<jetty.surefire.argLine>-Dfile.encoding=UTF-8 -Duser.language=en -Duser.region=US -showversion -Xmx2g -Xms2g -Xlog:gc:stderr:time,level,tags</jetty.surefire.argLine>
|
||||
|
||||
<!-- some maven plugins versions -->
|
||||
<maven.surefire.version>3.0.0-M4</maven.surefire.version>
|
||||
<maven.surefire.version>3.0.0-M5</maven.surefire.version>
|
||||
<maven.compiler.plugin.version>3.8.1</maven.compiler.plugin.version>
|
||||
<maven.dependency.plugin.version>3.1.1</maven.dependency.plugin.version>
|
||||
<maven.resources.plugin.version>3.1.0</maven.resources.plugin.version>
|
||||
<maven.source.plugin.version>3.0.1</maven.source.plugin.version>
|
||||
<maven.war.plugin.version>3.2.2</maven.war.plugin.version>
|
||||
<maven.dependency.plugin.version>3.1.2</maven.dependency.plugin.version>
|
||||
<maven.resources.plugin.version>3.2.0</maven.resources.plugin.version>
|
||||
<maven.source.plugin.version>3.2.1</maven.source.plugin.version>
|
||||
<maven.war.plugin.version>3.3.1</maven.war.plugin.version>
|
||||
<maven.plugin-tools.version>3.5.2</maven.plugin-tools.version>
|
||||
<maven.install.plugin.version>2.5.2</maven.install.plugin.version>
|
||||
<maven.deploy.plugin.version>2.8.2</maven.deploy.plugin.version>
|
||||
<maven.install.plugin.version>3.0.0-M1</maven.install.plugin.version>
|
||||
<maven.deploy.plugin.version>3.0.0-M1</maven.deploy.plugin.version>
|
||||
|
||||
<!-- testing -->
|
||||
<it.debug>false</it.debug>
|
||||
|
|
Loading…
Reference in New Issue