/*
* Copyright (c) 2010, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://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: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.grizzly.http.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLEngine;
import org.glassfish.grizzly.Connection;
import org.glassfish.grizzly.EmptyCompletionHandler;
import org.glassfish.grizzly.GracefulShutdownListener;
import org.glassfish.grizzly.Grizzly;
import org.glassfish.grizzly.GrizzlyFuture;
import org.glassfish.grizzly.PortRange;
import org.glassfish.grizzly.ShutdownContext;
import org.glassfish.grizzly.filterchain.Filter;
import org.glassfish.grizzly.filterchain.FilterChain;
import org.glassfish.grizzly.filterchain.FilterChainContext;
import org.glassfish.grizzly.filterchain.ShutdownEvent;
import org.glassfish.grizzly.http.CompressionConfig;
import org.glassfish.grizzly.http.CompressionConfig.CompressionMode;
import org.glassfish.grizzly.http.HttpCodecFilter;
import org.glassfish.grizzly.http.KeepAlive;
import org.glassfish.grizzly.http.server.filecache.FileCache;
import org.glassfish.grizzly.http.util.MimeHeaders;
import org.glassfish.grizzly.impl.FutureImpl;
import org.glassfish.grizzly.monitoring.MonitoringUtils;
import org.glassfish.grizzly.nio.transport.TCPNIOServerConnection;
import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder;
import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
import org.glassfish.grizzly.strategies.SameThreadIOStrategy;
import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
import org.glassfish.grizzly.utils.ArraySet;
import org.glassfish.grizzly.utils.Futures;
public class NetworkListener {
private static final Logger LOGGER = Grizzly.logger(NetworkListener.class);
The default network host to which the HttpServer
will bind to in order to service HTTP
requests.
/**
* The default network host to which the {@link HttpServer} will bind to in order to service <code>HTTP</code>
* requests.
*/
public static final String DEFAULT_NETWORK_HOST = "0.0.0.0";
The default network port to which the HttpServer
will bind to in order to service HTTP
requests.
/**
* The default network port to which the {@link HttpServer} will bind to in order to service <code>HTTP</code>
* requests.
*/
public static final int DEFAULT_NETWORK_PORT = 8080;
The network host to which the HttpServer will bind to in order to service HTTP
requests. If not explicitly set, the value of DEFAULT_NETWORK_HOST
will be used.
/**
* The network host to which the <code>HttpServer<code> will bind to in order to service <code>HTTP</code> requests.
* If not explicitly set, the value of {@link #DEFAULT_NETWORK_HOST} will be used.
*/
private String host = DEFAULT_NETWORK_HOST;
The network port to which the HttpServer will bind to in order to service HTTP
requests. If not explicitly set, the value of DEFAULT_NETWORK_PORT
will be used.
/**
* The network port to which the <code>HttpServer<code> will bind to in order to service <code>HTTP</code> requests.
* If not explicitly set, the value of {@link #DEFAULT_NETWORK_PORT} will be used.
*/
private int port = DEFAULT_NETWORK_PORT;
The flag indicates if the HttpServer will be bounnd to an inherited Channel.
If not explicitly set, the HttpServer
will be bound to DEFAULT_NETWORK_HOST
:DEFAULT_NETWORK_PORT
.
/**
* The flag indicates if the <code>HttpServer<code> will be bounnd to an inherited Channel.
* If not explicitly set, the <code>HttpServer</code> will be bound to {@link #DEFAULT_NETWORK_HOST}:{@link #DEFAULT_NETWORK_PORT}.
*/
private final boolean isBindToInherited;
The time, in seconds, for which a request must complete processing.
/**
* The time, in seconds, for which a request must complete processing.
*/
private int transactionTimeout = -1;
The network port range to which the HttpServer will bind to
in order to service HTTP
requests. If not explicitly set, the value of port
will be used.
/**
* The network port range to which the <code>HttpServer<code> will bind to
* in order to service <code>HTTP</code> requests.
* If not explicitly set, the value of {@link #port} will be used.
*/
private PortRange portRange;
The logical name
of this particular NetworkListener
instance.
/**
* The logical <code>name</code> of this particular <code>NetworkListener</code> instance.
*/
private final String name;
The configuration for HTTP keep-alive connections
/**
* The configuration for HTTP keep-alive connections
*/
private final KeepAlive keepAliveConfig = new KeepAlive();
The Grizzly FilterChain
used to process incoming and outgoing network I/O. /**
* The Grizzly {@link FilterChain} used to process incoming and outgoing network I/O.
*/
private FilterChain filterChain;
The TCPNIOTransport
used by this NetworkListener
/**
* The {@link TCPNIOTransport} used by this <code>NetworkListener</code>
*/
private TCPNIOTransport transport;
TCP Server Connection
responsible for accepting client connections /**
* TCP Server {@link Connection} responsible for accepting client connections
*/
private TCPNIOServerConnection serverConnection;
The default error page generator
/**
* The default error page generator
*/
private ErrorPageGenerator defaultErrorPageGenerator;
The HTTP server SessionManager
. /**
* The HTTP server {@link SessionManager}.
*/
private SessionManager sessionManager;
{
final TCPNIOTransportBuilder builder = TCPNIOTransportBuilder.newInstance();
final int coresCount = Runtime.getRuntime().availableProcessors() * 2;
transport = builder
.setIOStrategy(SameThreadIOStrategy.getInstance())
.setWorkerThreadPoolConfig(ThreadPoolConfig.defaultConfig()
.setPoolName("Grizzly-worker")
.setCorePoolSize(coresCount)
.setMaxPoolSize(coresCount)
.setMemoryManager(builder.getMemoryManager()))
.build();
}
Flag indicating whether or not this listener is secure. Defaults to false
/**
* Flag indicating whether or not this listener is secure. Defaults to <code>false</code>
*/
private boolean secure;
AddOns registered for the network listener
/**
* AddOns registered for the network listener
*/
private final ArraySet<AddOn> addons = new ArraySet<>(AddOn.class);
Flag indicating whether or not the chunked transfer encoding is enabled. Defaults to true
.
/**
* Flag indicating whether or not the chunked transfer encoding is enabled. Defaults to <code>true</code>.
*/
private boolean chunkingEnabled = true;
Configuration for the SSLEngine
that will be used for secure listeners. /**
* Configuration for the {@link SSLEngine} that will be used for secure listeners.
*/
private SSLEngineConfigurator sslEngineConfig;
The maximum size of an incoming HTTP
message.
/**
* The maximum size of an incoming <code>HTTP</code> message.
*/
private int maxHttpHeaderSize = -1;
FileCache
to be used by this NetworkListener
.
/**
* {@link FileCache} to be used by this <code>NetworkListener</code>.
*/
private final FileCache fileCache = new FileCache();
Maximum size, in bytes, of all data waiting to be written.
/**
* Maximum size, in bytes, of all data waiting to be written.
*/
private volatile int maxPendingBytes = -1;
Flag indicating the state of this listener.
/**
* Flag indicating the state of this listener.
*/
private State state = State.STOPPED;
Future to control graceful shutdown status
/**
* Future to control graceful shutdown status
*/
private FutureImpl<NetworkListener> shutdownFuture;
Shutdown event.
/**
* Shutdown event.
*/
private ShutdownEvent shutdownEvent;
HttpServerFilter
associated with this listener. /**
* {@link HttpServerFilter} associated with this listener.
*/
private HttpServerFilter httpServerFilter;
HttpCodecFilter
associated with this listener. /**
* {@link HttpCodecFilter} associated with this listener.
*/
private HttpCodecFilter httpCodecFilter;
/**
* {@link CompressionConfig}
*/
private final CompressionConfig compressionConfig = new CompressionConfig();
private boolean authPassThroughEnabled;
private int maxFormPostSize = 2 * 1024 * 1024;
private int maxBufferedPostSize = 2 * 1024 * 1024;
private String restrictedUserAgents;
private int uploadTimeout;
private boolean disableUploadTimeout;
private boolean traceEnabled;
private String uriEncoding;
private Boolean sendFileEnabled;
The auxiliary configuration, which might be used, when Grizzly HttpServer
is running behind some HTTP gateway like reverse proxy or load balancer.
/**
* The auxiliary configuration, which might be used, when Grizzly HttpServer
* is running behind some HTTP gateway like reverse proxy or load balancer.
*/
private BackendConfiguration backendConfiguration;
private int maxRequestHeaders = MimeHeaders.MAX_NUM_HEADERS_DEFAULT;
private int maxResponseHeaders = MimeHeaders.MAX_NUM_HEADERS_DEFAULT;
// ------------------------------------------------------------ Constructors
Constructs a new NetworkListener
using the specified name
. The listener's host and port will default to DEFAULT_NETWORK_HOST
and DEFAULT_NETWORK_PORT
.
Params: - name – the logical name of the listener.
/**
* <p> Constructs a new <code>NetworkListener</code> using the specified <code>name</code>. The listener's host and
* port will default to {@link #DEFAULT_NETWORK_HOST} and {@link #DEFAULT_NETWORK_PORT}. </p>
*
* @param name the logical name of the listener.
*/
public NetworkListener(final String name) {
this(name, false);
}
Constructs a new NetworkListener
using the specified name
, which,
depending on isBindToInherited
will or will not be bound to an inherited Channel.
Params: - name – the logical name of the listener.
- isBindToInherited – if true the
NetworkListener
will be bound to an inherited Channel, otherwise default DEFAULT_NETWORK_HOST
and DEFAULT_NETWORK_PORT
will be used.
See Also:
/**
* <p> Constructs a new <code>NetworkListener</code> using the specified <code>name</code>, which,
* depending on <code>isBindToInherited</code> will or will not be bound to an inherited Channel.</p>
*
* @param name the logical name of the listener.
* @param isBindToInherited if <tt>true</tt> the <code>NetworkListener</code> will be
* bound to an inherited Channel, otherwise default {@link #DEFAULT_NETWORK_HOST} and {@link #DEFAULT_NETWORK_PORT}
* will be used.
*
* @see System#inheritedChannel()
*/
public NetworkListener(final String name, final boolean isBindToInherited) {
validateArg("name", name);
this.name = name;
this.isBindToInherited = isBindToInherited;
}
Constructs a new NetworkListener
using the specified name
and host
. The listener's port will default to DEFAULT_NETWORK_PORT
.
Params: - name – the logical name of the listener.
- host – the network host to which this listener will bind.
/**
* <p> Constructs a new <code>NetworkListener</code> using the specified <code>name</code> and <code>host</code>.
* The listener's port will default to {@link #DEFAULT_NETWORK_PORT}. </p>
*
* @param name the logical name of the listener.
* @param host the network host to which this listener will bind.
*/
public NetworkListener(final String name, final String host) {
this(name, host, DEFAULT_NETWORK_PORT);
}
Constructs a new NetworkListener
using the specified name
, host
, and
port
.
Params: - name – the logical name of the listener.
- host – the network host to which this listener will bind.
- port – the network port to which this listener will bind..
/**
* <p> Constructs a new <code>NetworkListener</code> using the specified <code>name</code>, <code>host</code>, and
* <code>port</code>. </p>
*
* @param name the logical name of the listener.
* @param host the network host to which this listener will bind.
* @param port the network port to which this listener will bind..
*/
public NetworkListener(final String name, final String host, final int port) {
validateArg("name", name);
validateArg("host", host);
if (port < 0) {
throw new IllegalArgumentException("Invalid port");
}
this.name = name;
this.host = host;
this.port = port;
isBindToInherited = false;
}
Constructs a new NetworkListener
using the specified name
, host
, and
port
.
Params: - name – the logical name of the listener.
- host – the network host to which this listener will bind.
- portRange – the network port range to which this listener will bind..
/**
* <p> Constructs a new <code>NetworkListener</code> using the specified <code>name</code>, <code>host</code>, and
* <code>port</code>. </p>
*
* @param name the logical name of the listener.
* @param host the network host to which this listener will bind.
* @param portRange the network port range to which this listener will bind..
*/
public NetworkListener(final String name,
final String host,
final PortRange portRange) {
validateArg("name", name);
validateArg("host", host);
this.name = name;
this.host = host;
this.port = -1;
this.portRange = portRange;
isBindToInherited = false;
}
// ----------------------------------------------------------- Configuration
Returns: the logical name of this listener.
/**
* @return the logical name of this listener.
*/
public String getName() {
return name;
}
Returns: the network host to which this listener is configured to bind to.
/**
* @return the network host to which this listener is configured to bind to.
*/
public String getHost() {
return host;
}
Returns: the network port to which this listener is configured to bind to. If the HttpServer
has not been started yet - the returned value may be: -1, if PortRange
will be used to bind the listener; 0, if the port will be assigned by OS;
0 < N < 65536, the port this listener will be bound to. If HttpServer
has been started - the value returned is the port the this listener is bound to.
/**
* @return the network port to which this listener is configured to bind to.
* If the {@link HttpServer} has not been started yet - the returned value
* may be:
* <tt>-1</tt>, if {@link PortRange} will be used to bind the listener;
* <tt>0</tt>, if the port will be assigned by OS;
* <tt>0 < N < 65536</tt>, the port this listener will be bound to.
* If {@link HttpServer} has been started - the value returned is the port the
* this listener is bound to.
*/
public int getPort() {
return port;
}
Returns: the network port range to which this listener is configured to bind to.
/**
* @return the network port range to which this listener is configured to bind to.
*/
public PortRange getPortRange() {
return portRange;
}
Returns: the configuration for the keep-alive HTTP connections.
/**
* @return the configuration for the keep-alive HTTP connections.
*/
public KeepAlive getKeepAlive() {
return keepAliveConfig;
}
Returns: the TCPNIOTransport
used by this listener.
/**
* @return the {@link TCPNIOTransport} used by this listener.
*/
public TCPNIOTransport getTransport() {
return transport;
}
This allows the developer to specify a custom TCPNIOTransport
implementation to be used by this listener.
Attempts to change the transport implementation while the listener is running will be ignored.
Params: - transport – a custom
TCPNIOTransport
implementation.
/**
* <p> This allows the developer to specify a custom {@link TCPNIOTransport} implementation to be used by this
* listener. </p>
* <p/>
* <p> Attempts to change the transport implementation while the listener is running will be ignored. </p>
*
* @param transport a custom {@link TCPNIOTransport} implementation.
*/
public void setTransport(final TCPNIOTransport transport) {
if (transport == null) {
return;
}
if (!transport.isStopped()) {
return;
}
this.transport = transport;
}
Returns: Grizzly server Connection
, that is responsible for accepting incoming client connections Since: 2.3.24
/**
* @return Grizzly server {@link Connection}, that is responsible for
* accepting incoming client connections
* @since 2.3.24
*/
public Connection getServerConnection() {
return serverConnection;
}
Return the array of the registered AddOn
s. Please note, possible array modifications wont affect the NetworkListener
's addons list. Returns: the array of the registered AddOn
s.
/**
* Return the array of the registered {@link AddOn}s.
* Please note, possible array modifications wont affect the
* {@link NetworkListener}'s addons list.
*
* @return the array of the registered {@link AddOn}s.
*/
public AddOn[] getAddOns() {
return addons.obtainArrayCopy();
}
Returns the direct addons collection, registered on the NetworkListener.
Returns: the direct addons collection, registered on the NetworkListener.
/**
* Returns the direct addons collection, registered on the NetworkListener.
* @return the direct addons collection, registered on the NetworkListener.
*/
protected ArraySet<AddOn> getAddOnSet() {
return addons;
}
Registers AddOn
on this NetworkListener. Params: - addon – the
AddOn
to be registered.
Returns: true, if the AddOn
wasn't registered before, otherwise the existing AddOn
will be replaced and this method returns false.
/**
* Registers {@link AddOn} on this NetworkListener.
* @param addon the {@link AddOn} to be registered.
*
* @return <tt>true</tt>, if the {@link AddOn} wasn't registered before,
* otherwise the existing {@link AddOn} will be replaced and this method
* returns <tt>false</tt>.
*/
public boolean registerAddOn(final AddOn addon) {
return addons.add(addon);
}
Deregisters AddOn
from this NetworkListener. Params: - addon – the
AddOn
to deregister.
Returns: true, if the AddOn
was successfully removed, or false the the AddOn
wasn't registered on the NetworkListener.
/**
* Deregisters {@link AddOn} from this NetworkListener.
* @param addon the {@link AddOn} to deregister.
*
* @return <tt>true</tt>, if the {@link AddOn} was successfully removed, or
* <tt>false</tt> the the {@link AddOn} wasn't registered on the
* NetworkListener.
*/
public boolean deregisterAddOn(final AddOn addon) {
return addons.remove(addon);
}
Returns: true
if the HTTP response bodies should be chunked if not content length has been explicitly
specified.
/**
* @return <code>true</code> if the HTTP response bodies should be chunked if not content length has been explicitly
* specified.
*/
public boolean isChunkingEnabled() {
return chunkingEnabled;
}
Enable/disable chunking of an HTTP response body if no content length has been explictly specified. Chunking is
enabled by default.
Params: - chunkingEnabled –
true
to enable chunking; false
to disable.
/**
* Enable/disable chunking of an HTTP response body if no content length has been explictly specified. Chunking is
* enabled by default.
*
* @param chunkingEnabled <code>true</code> to enable chunking; <code>false</code> to disable.
*/
public void setChunkingEnabled(boolean chunkingEnabled) {
this.chunkingEnabled = chunkingEnabled;
}
Returns: true
if this is a secure listener, otherwise false
. Listeners are not secure
by default.
/**
* @return <code>true</code> if this is a secure listener, otherwise <code>false</code>. Listeners are not secure
* by default.
*/
public boolean isSecure() {
return secure;
}
Enable or disable security for this listener.
Attempts to change this value while the listener is running will be ignored.
Params: - secure – if
true
this listener will be secure.
/**
* <p> Enable or disable security for this listener. </p>
* <p/>
* <p> Attempts to change this value while the listener is running will be ignored. </p>
*
* @param secure if <code>true</code> this listener will be secure.
*/
public void setSecure(final boolean secure) {
if (!isStopped()) {
return;
}
this.secure = secure;
}
Get the HTTP request scheme, which if non-null overrides default one
picked up by framework during runtime.
Returns: the HTTP request scheme Since: 2.2.4
/**
* Get the HTTP request scheme, which if non-null overrides default one
* picked up by framework during runtime.
*
* @return the HTTP request scheme
*
* @since 2.2.4
*/
public String getScheme() {
final BackendConfiguration config = backendConfiguration;
return config != null ? config.getScheme() : null;
}
Set the HTTP request scheme, which if non-null overrides default one
picked up by framework during runtime.
Params: - scheme – the HTTP request scheme
Since: 2.2.4
/**
* Set the HTTP request scheme, which if non-null overrides default one
* picked up by framework during runtime.
*
* @param scheme the HTTP request scheme
*
* @since 2.2.4
*/
public void setScheme(String scheme) {
BackendConfiguration config = backendConfiguration;
if (config == null) {
config = new BackendConfiguration();
}
config.setScheme(scheme);
this.backendConfiguration = config;
}
Returns: the auxiliary configuration, which might be used, when Grizzly
HttpServer is running behind HTTP gateway like reverse proxy or load balancer. Since: 2.3.18
/**
* @return the auxiliary configuration, which might be used, when Grizzly
* HttpServer is running behind HTTP gateway like reverse proxy or load balancer.
*
* @since 2.3.18
*/
public BackendConfiguration getBackendConfiguration() {
return backendConfiguration;
}
Sets the auxiliary configuration, which might be used, when Grizzly HttpServer
is running behind HTTP gateway like reverse proxy or load balancer.
Params: - backendConfiguration –
BackendConfiguration
Since: 2.3.18
/**
* Sets the auxiliary configuration, which might be used, when Grizzly HttpServer
* is running behind HTTP gateway like reverse proxy or load balancer.
*
* @param backendConfiguration {@link BackendConfiguration}
* @since 2.3.18
*/
public void setBackendConfiguration(BackendConfiguration backendConfiguration) {
this.backendConfiguration = backendConfiguration;
}
Returns the maximum number of headers allowed for a request.
Since: 2.2.11
/**
* Returns the maximum number of headers allowed for a request.
*
* @since 2.2.11
*/
public int getMaxRequestHeaders() {
return maxRequestHeaders;
}
Sets the maximum number of headers allowed for a request.
If the specified value is less than zero, then there may be an
unlimited number of headers (memory permitting).
Since: 2.2.11
/**
* Sets the maximum number of headers allowed for a request.
*
* If the specified value is less than zero, then there may be an
* unlimited number of headers (memory permitting).
*
* @since 2.2.11
*/
public void setMaxRequestHeaders(int maxRequestHeaders) {
this.maxRequestHeaders = maxRequestHeaders;
}
Returns the maximum number of headers allowed for a response.
Since: 2.2.11
/**
* Returns the maximum number of headers allowed for a response.
*
* @since 2.2.11
*/
public int getMaxResponseHeaders() {
return maxResponseHeaders;
}
Sets the maximum number of headers allowed for a response.
If the specified value is less than zero, then there may be an
unlimited number of headers (memory permitting).
Since: 2.2.11
/**
* Sets the maximum number of headers allowed for a response.
*
* If the specified value is less than zero, then there may be an
* unlimited number of headers (memory permitting).
*
* @since 2.2.11
*/
public void setMaxResponseHeaders(int maxResponseHeaders) {
this.maxResponseHeaders = maxResponseHeaders;
}
Returns: the SSLEngine
configuration for this listener.
/**
* @return the {@link SSLEngine} configuration for this listener.
*/
public SSLEngineConfigurator getSslEngineConfig() {
return sslEngineConfig;
}
Provides customization of the SSLEngine
used by this listener.
Attempts to change this value while the listener is running will be ignored.
Params: - sslEngineConfig – custom SSL configuration.
/**
* <p> Provides customization of the {@link SSLEngine} used by this listener. </p>
* <p/>
* <p> Attempts to change this value while the listener is running will be ignored. </p>
*
* @param sslEngineConfig custom SSL configuration.
*/
public void setSSLEngineConfig(final SSLEngineConfigurator sslEngineConfig) {
if (!isStopped()) {
return;
}
this.sslEngineConfig = sslEngineConfig;
}
Returns: the maximum header size for an HTTP request.
/**
* @return the maximum header size for an HTTP request.
*/
public int getMaxHttpHeaderSize() {
return maxHttpHeaderSize;
}
Configures the maximum header size for an HTTP request.
Attempts to change this value while the listener is running will be ignored.
Params: - maxHttpHeaderSize – the maximum header size for an HTTP request.
/**
* <p> Configures the maximum header size for an HTTP request. </p>
* <p/>
* <p> Attempts to change this value while the listener is running will be ignored. </p>
*
* @param maxHttpHeaderSize the maximum header size for an HTTP request.
*/
public void setMaxHttpHeaderSize(final int maxHttpHeaderSize) {
if (!isStopped()) {
return;
}
this.maxHttpHeaderSize = maxHttpHeaderSize;
}
Returns: the FilterChain
used to by the TCPNIOTransport
associated with this listener.
/**
* @return the {@link FilterChain} used to by the {@link TCPNIOTransport} associated with this listener.
*/
public FilterChain getFilterChain() {
return filterChain;
}
Specifies the FilterChain
to be used by the TCPNIOTransport
associated with this listener.
Attempts to change this value while the listener is running will be ignored.
Params: - filterChain – the
FilterChain
.
/**
* <p> Specifies the {@link FilterChain} to be used by the {@link TCPNIOTransport} associated with this listener.
* </p>
* <p/>
* <p> Attempts to change this value while the listener is running will be ignored. </p>
*
* @param filterChain the {@link FilterChain}.
*/
void setFilterChain(final FilterChain filterChain) {
if (!isStopped()) {
return;
}
if (filterChain != null) {
this.filterChain = filterChain;
}
}
Returns: the FileCache
associated with this listener.
/**
* @return the {@link FileCache} associated with this listener.
*/
public FileCache getFileCache() {
return fileCache;
}
Returns: the maximum size, in bytes, of all data waiting to be written to the associated Connection
. If not explicitly set, the value will be -1 which effectively disables resource enforcement.
/**
* @return the maximum size, in bytes, of all data waiting to be written to the associated {@link Connection}.
* If not explicitly set, the value will be -1 which effectively disables
* resource enforcement.
*/
public int getMaxPendingBytes() {
return maxPendingBytes;
}
The maximum size, in bytes, of all data waiting to be written to the associated Connection
. If the value is zero or less, then no resource enforcement will take place. Params: - maxPendingBytes – the maximum size, in bytes, of all data waiting to be written to the associated
Connection
.
/**
* The maximum size, in bytes, of all data waiting to be written to the associated {@link Connection}.
* If the value is zero or less, then no resource enforcement will take place.
*
* @param maxPendingBytes the maximum size, in bytes, of all data waiting to be written to the associated {@link
* Connection}.
*/
public void setMaxPendingBytes(int maxPendingBytes) {
this.maxPendingBytes = maxPendingBytes;
transport.getAsyncQueueIO().getWriter().setMaxPendingBytesPerConnection(maxPendingBytes);
}
// ---------------------------------------------------------- Public Methods
Returns: true
if this listener has been paused, otherwise false
/**
* @return <code>true</code> if this listener has been paused, otherwise <code>false</code>
*/
public boolean isPaused() {
return state == State.PAUSED;
}
Returns: true
if the listener has been started, otherwise false
.
/**
* @return <code>true</code> if the listener has been started, otherwise <code>false</code>.
*/
public boolean isStarted() {
return state != State.STOPPED;
}
Starts the listener.
Throws: - IOException – if an error occurs when attempting to start the listener.
/**
* <p> Starts the listener. </p>
*
* @throws IOException if an error occurs when attempting to start the listener.
*/
public synchronized void start() throws IOException {
if (isStarted()) {
return;
}
shutdownFuture = null;
if (filterChain == null) {
throw new IllegalStateException("No FilterChain available."); // i18n
}
transport.setProcessor(filterChain);
if (isBindToInherited) {
serverConnection = transport.bindToInherited();
} else {
serverConnection = (port != -1) ?
transport.bind(host, port) :
transport.bind(host, portRange, transport.getServerConnectionBackLog());
}
port = ((InetSocketAddress) serverConnection.getLocalAddress()).getPort();
transport.addShutdownListener(new GracefulShutdownListener() {
@Override
public void shutdownRequested(final ShutdownContext shutdownContext) {
final FutureImpl<NetworkListener> shutdownFutureLocal = shutdownFuture;
filterChain.fireEventDownstream(serverConnection,
shutdownEvent,
new EmptyCompletionHandler<FilterChainContext>() {
@Override
public void completed(final FilterChainContext result) {
final Set<Callable<Filter>> tasks = shutdownEvent.getShutdownTasks();
if (!tasks.isEmpty()) {
final ExecutorService shutdownService = Executors.newFixedThreadPool(Math.min(5, tasks.size()) + 1);
shutdownService.submit(new Runnable() {
@Override
public void run() {
try {
final List<Future<Filter>> futures;
if (shutdownEvent.getGracePeriod() == -1) {
futures = shutdownService.invokeAll(tasks);
} else {
futures = shutdownService.invokeAll(tasks,
shutdownEvent.getGracePeriod(),
shutdownEvent.getTimeUnit());
}
for (Future<Filter> future : futures) {
try {
future.get();
} catch (ExecutionException e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE,
"Error processing shutdown task filter.",
e);
}
}
}
shutdownFutureLocal.result(NetworkListener.this);
shutdownContext.ready();
shutdownService.shutdownNow();
} catch (InterruptedException e) {
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.warning("NetworkListener shutdown interrupted.");
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, e.toString(), e);
}
}
}
});
}
}
});
}
@Override
public void shutdownForced() {
serverConnection = null;
if (shutdownFuture != null) {
shutdownFuture.result(NetworkListener.this);
}
}
});
transport.start();
state = State.RUNNING;
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO,
"Started listener bound to [{0}]",
host + ':' + port);
}
}
public synchronized GrizzlyFuture<NetworkListener> shutdown(final long gracePeriod,
final TimeUnit timeUnit) {
if (state == State.STOPPING
|| state == State.STOPPED) {
return shutdownFuture != null ? shutdownFuture :
Futures.createReadyFuture(this);
} else if (state == State.PAUSED) {
resume();
}
shutdownEvent = new ShutdownEvent(gracePeriod, timeUnit);
state = State.STOPPING;
shutdownFuture = Futures.createSafeFuture();
transport.shutdown(gracePeriod, timeUnit);
return shutdownFuture;
}
Gracefully shuts down the listener.
Any exceptions thrown during the shutdown process will be propagated to the returned GrizzlyFuture
. Returns: GrizzlyFuture
/**
* <p> Gracefully shuts down the listener. </p> Any exceptions
* thrown during the shutdown process will be propagated to the returned
* {@link GrizzlyFuture}.
* @return {@link GrizzlyFuture}
*/
public synchronized GrizzlyFuture<NetworkListener> shutdown() {
return shutdown(-1, TimeUnit.MILLISECONDS);
}
Immediately shuts down the listener.
Throws: - IOException – if an error occurs when attempting to shut down the listener
/**
* <p> Immediately shuts down the listener. </p>
*
* @throws IOException if an error occurs when attempting to shut down the listener
*/
public synchronized void shutdownNow() throws IOException {
if (state == State.STOPPED) {
return;
}
try {
serverConnection = null;
transport.shutdownNow();
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO,
"Stopped listener bound to [{0}]",
host + ':' + port);
}
} finally {
state = State.STOPPED;
if (shutdownFuture != null) {
shutdownFuture.result(this);
}
}
}
Immediately shuts down the listener.
Throws: - IOException – if an error occurs when attempting to shut down the listener
Deprecated: use shutdownNow()
/**
* <p> Immediately shuts down the listener. </p>
*
* @throws IOException if an error occurs when attempting to shut down the listener
* @deprecated use {@link #shutdownNow()}
*/
public void stop() throws IOException {
shutdownNow();
}
Pauses the listener.
/**
* <p> Pauses the listener. </p>
*/
public synchronized void pause() {
if (state != State.RUNNING) {
return;
}
transport.pause();
state = State.PAUSED;
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO,
"Paused listener bound to [{0}]",
host + ':' + port);
}
}
Resumes a paused listener.
/**
* <p> Resumes a paused listener. </p>
*/
public synchronized void resume() {
if (state != State.PAUSED) {
return;
}
transport.resume();
state = State.RUNNING;
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO,
"Resumed listener bound to [{0}]",
host + ':' + port);
}
}
Returns: a value containing the name, host, port, and secure status of this listener.
/**
* @return a value containing the name, host, port, and secure status of this listener.
*/
@Override
public String toString() {
return "NetworkListener{" +
"name='" + name + '\'' +
", host='" + host + '\'' +
", port=" + port +
", secure=" + secure +
", state=" + state +
'}';
}
public Object createManagementObject() {
return MonitoringUtils.loadJmxObject(
"org.glassfish.grizzly.http.server.jmx.NetworkListener",
this, NetworkListener.class);
}
public HttpServerFilter getHttpServerFilter() {
if (httpServerFilter == null) {
final int idx = filterChain.indexOfType(HttpServerFilter.class);
if (idx == -1) {
return null;
}
httpServerFilter = (HttpServerFilter) filterChain.get(idx);
}
return httpServerFilter;
}
public HttpCodecFilter getHttpCodecFilter() {
if (httpCodecFilter == null) {
final int idx = filterChain.indexOfType(HttpCodecFilter.class);
if (idx == -1) {
return null;
}
httpCodecFilter = (HttpCodecFilter) filterChain.get(idx);
}
return httpCodecFilter;
}
// --------------------------------------------------------- Private Methods
private static void validateArg(final String name, final String value) {
if (value == null || value.length() == 0) {
throw new IllegalArgumentException("Argument "
+ name
+ " cannot be "
+ (value == null
? "null"
: "have a zero length")); // I18n
}
}
public boolean isAuthPassThroughEnabled() {
return authPassThroughEnabled;
}
public void setAuthPassThroughEnabled(final boolean authPassthroughEnabled) {
this.authPassThroughEnabled = authPassthroughEnabled;
}
Returns CompressionConfig
configuration. Since: 2.3.5
/**
* Returns {@link CompressionConfig} configuration.
*
* @since 2.3.5
*/
public CompressionConfig getCompressionConfig() {
return compressionConfig;
}
Deprecated: use getCompressionConfig().getCompressionMode().name()
/**
* @deprecated use <tt>getCompressionConfig().getCompressionMode().name()</tt>
*/
public String getCompression() {
return compressionConfig.getCompressionMode().name();
}
Deprecated: use getCompressionConfig().setCompressionMode(mode)
/**
* @deprecated use <tt>getCompressionConfig().setCompressionMode(mode)</tt>
*/
public void setCompression(final String compression) {
compressionConfig.setCompressionMode(CompressionMode.fromString(compression));
}
Deprecated: use getCompressionConfig().getCompressionMinSize()
/**
* @deprecated use <tt>getCompressionConfig().getCompressionMinSize()</tt>
*/
public int getCompressionMinSize() {
return compressionConfig.getCompressionMinSize();
}
Deprecated: use getCompressionConfig().setCompressionMinSize(int)
/**
* @deprecated use <tt>getCompressionConfig().setCompressionMinSize(int)</tt>
*/
public void setCompressionMinSize(final int compressionMinSize) {
compressionConfig.setCompressionMinSize(compressionMinSize);
}
Deprecated: use getCompressionConfig().getCompressibleMimeTypes()
/**
* @deprecated use <tt>getCompressionConfig().getCompressibleMimeTypes()</tt>
*/
public String getCompressibleMimeTypes() {
return setToString(compressionConfig.getCompressibleMimeTypes());
}
Deprecated: use getCompressionConfig().setCompressibleMimeTypes(Set<String>)
/**
* @deprecated use <tt>getCompressionConfig().setCompressibleMimeTypes(Set<String>)</tt>
*/
public void setCompressibleMimeTypes(final String compressibleMimeTypes) {
compressionConfig.setCompressibleMimeTypes(stringToSet(compressibleMimeTypes));
}
Deprecated: use getCompressionConfig().getNoCompressionUserAgents()
/**
* @deprecated use <tt>getCompressionConfig().getNoCompressionUserAgents()</tt>
*/
public String getNoCompressionUserAgents() {
return setToString(compressionConfig.getNoCompressionUserAgents());
}
Deprecated: use getCompressionConfig().setNoCompressionUserAgents(Set<String>)
/**
* @deprecated use <tt>getCompressionConfig().setNoCompressionUserAgents(Set<String>)</tt>
*/
public void setNoCompressionUserAgents(final String noCompressionUserAgents) {
compressionConfig.setNoCompressionUserAgents(stringToSet(noCompressionUserAgents));
}
public boolean isDisableUploadTimeout() {
return disableUploadTimeout;
}
public void setDisableUploadTimeout(final boolean disableUploadTimeout) {
this.disableUploadTimeout = disableUploadTimeout;
}
Gets the maximum size of the POST body generated by an HTML form.
-1
value means no size limits applied.
Since: 2.3
/**
* Gets the maximum size of the POST body generated by an HTML form.
* <code>-1</code> value means no size limits applied.
*
* @since 2.3
*/
public int getMaxFormPostSize() {
return maxFormPostSize;
}
Sets the maximum size of the POST body generated by an HTML form.
-1
value means no size limits applied.
Since: 2.3
/**
* Sets the maximum size of the POST body generated by an HTML form.
* <code>-1</code> value means no size limits applied.
*
* @since 2.3
*/
public void setMaxFormPostSize(final int maxFormPostSize) {
this.maxFormPostSize = maxFormPostSize < 0 ? -1 : maxFormPostSize;
}
Gets the maximum POST body size, which can buffered in memory.
-1
value means no size limits applied.
Since: 2.3
/**
* Gets the maximum POST body size, which can buffered in memory.
* <code>-1</code> value means no size limits applied.
*
* @since 2.3
*/
public int getMaxBufferedPostSize() {
return maxBufferedPostSize;
}
Sets the maximum POST body size, which can buffered in memory.
-1
value means no size limits applied.
Since: 2.3
/**
* Sets the maximum POST body size, which can buffered in memory.
* <code>-1</code> value means no size limits applied.
*
* @since 2.3
*/
public void setMaxBufferedPostSize(final int maxBufferedPostSize) {
this.maxBufferedPostSize = maxBufferedPostSize < 0 ? -1 : maxBufferedPostSize;
}
public String getRestrictedUserAgents() {
return restrictedUserAgents;
}
public void setRestrictedUserAgents(final String restrictedUserAgents) {
this.restrictedUserAgents = restrictedUserAgents;
}
public boolean isTraceEnabled() {
return traceEnabled;
}
public void setTraceEnabled(final boolean traceEnabled) {
this.traceEnabled = traceEnabled;
}
public int getUploadTimeout() {
return uploadTimeout;
}
public void setUploadTimeout(final int uploadTimeout) {
this.uploadTimeout = uploadTimeout;
}
public String getUriEncoding() {
return uriEncoding;
}
public void setUriEncoding(final String uriEncoding) {
this.uriEncoding = uriEncoding;
}
Returns: The timeout, in seconds, within which a request must complete
its processing. If not explicitly set, no transaction timeout will
be enforced.
/**
* @return The timeout, in seconds, within which a request must complete
* its processing. If not explicitly set, no transaction timeout will
* be enforced.
*/
public int getTransactionTimeout() {
return transactionTimeout;
}
Sets the time, in seconds, within which a request must complete its processing. A value less than or equal to zero will disable this timeout. Note that this configuration option is only considered when the transport's Transport.getWorkerThreadPool()
thread pool is used to run a HttpHandler
. Params: - transactionTimeout – timeout in seconds
/**
* Sets the time, in seconds, within which a request must complete its
* processing. A value less than or equal to zero will disable this
* timeout. Note that this configuration option is only considered when the
* transport's {@link org.glassfish.grizzly.Transport#getWorkerThreadPool()}
* thread pool is used to run a {@link HttpHandler}.
*
* @param transactionTimeout timeout in seconds
*/
public void setTransactionTimeout(final int transactionTimeout) {
this.transactionTimeout = transactionTimeout;
}
See Also: - isSendFileEnabled.isSendFileEnabled()
Since: 2.2
/**
* @see org.glassfish.grizzly.http.server.ServerFilterConfiguration#isSendFileEnabled()
*
* @since 2.2
*/
public boolean isSendFileEnabled() {
return sendFileEnabled;
}
See Also: - setSendFileEnabled.setSendFileEnabled(boolean)
Since: 2.2
/**
* @see ServerFilterConfiguration#setSendFileEnabled(boolean)
*
* @since 2.2
*/
public void setSendFileEnabled(boolean sendFileEnabled) {
this.sendFileEnabled = sendFileEnabled;
}
Returns: the NetworkListener default ErrorPageGenerator
.
/**
* @return the <tt>NetworkListener</tt> default {@link ErrorPageGenerator}.
*/
public ErrorPageGenerator getDefaultErrorPageGenerator() {
return defaultErrorPageGenerator;
}
Sets the NetworkListener default ErrorPageGenerator
. Params: - defaultErrorPageGenerator –
/**
* Sets the <tt>NetworkListener</tt> default {@link ErrorPageGenerator}.
*
* @param defaultErrorPageGenerator
*/
public void setDefaultErrorPageGenerator(
final ErrorPageGenerator defaultErrorPageGenerator) {
this.defaultErrorPageGenerator = defaultErrorPageGenerator;
}
See Also: Returns: the HTTP server SessionManager
/**
* @return the HTTP server {@link SessionManager}
*
* @see #setSessionManager
*/
public SessionManager getSessionManager() {
return sessionManager;
}
Sets the HTTP server SessionManager
. Params: - sessionManager –
SessionManager
/**
* Sets the HTTP server {@link SessionManager}.
*
* @param sessionManager {@link SessionManager}
*/
public void setSessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
boolean isSendFileExplicitlyConfigured() {
return (sendFileEnabled != null);
}
private boolean isStopped() {
return state == State.STOPPED || state == State.STOPPING;
}
private static String setToString(final Set<String> set) {
final StringBuilder sb = new StringBuilder(set.size() * 10);
for (String elem : set) {
if (sb.length() > 0) {
sb.append(',');
}
sb.append(elem);
}
return sb.toString();
}
private static Set<String> stringToSet(final String s) {
if (s == null) {
return null;
}
return new HashSet<>(Arrays.asList(s.split(",")));
}
}