/*
 * Copyright (c) 2007, 2018 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 com.sun.enterprise.v3.services.impl;

import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.HttpService;
import com.sun.enterprise.config.serverbeans.SystemProperty;
import com.sun.enterprise.config.serverbeans.VirtualServer;
import com.sun.enterprise.util.Result;
import com.sun.enterprise.util.StringUtils;
import com.sun.enterprise.v3.services.impl.monitor.GrizzlyMonitoring;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.glassfish.api.FutureProvider;
import org.glassfish.api.StartupRunLevel;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.container.EndpointRegistrationException;
import org.glassfish.api.container.RequestDispatcher;
import org.glassfish.api.deployment.ApplicationContainer;
import org.glassfish.api.event.EventListener;
import org.glassfish.api.event.EventTypes;
import org.glassfish.api.event.Events;
import org.glassfish.api.event.RestrictTo;
import org.glassfish.common.util.Constants;
import org.glassfish.grizzly.config.GenericGrizzlyListener;
import org.glassfish.grizzly.config.dom.NetworkConfig;
import org.glassfish.grizzly.config.dom.NetworkListener;
import org.glassfish.grizzly.config.dom.NetworkListeners;
import org.glassfish.grizzly.config.dom.Protocol;
import org.glassfish.grizzly.http.HttpCodecFilter;
import org.glassfish.grizzly.http.HttpProbe;
import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.server.util.Mapper;
import org.glassfish.grizzly.impl.FutureImpl;
import org.glassfish.grizzly.utils.Futures;
import org.glassfish.hk2.api.PostConstruct;
import org.glassfish.hk2.api.PreDestroy;
import org.glassfish.hk2.api.Rank;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.runlevel.RunLevel;
import org.glassfish.kernel.KernelLoggerInfo;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.config.ConfigBeanProxy;
import org.jvnet.hk2.config.ConfigSupport;
import org.jvnet.hk2.config.ObservableBean;
import org.jvnet.hk2.config.Transactions;

/**
 * The Network Service is responsible for starting grizzly and register the
 * top level proxy. It is also providing a runtime service where other
 * services (like admin for instance) can register endpoints proxy to
 * particular context root.
 *
 * @author Jerome Dochez
 */
@Service
@RunLevel(StartupRunLevel.VAL)
@Rank(Constants.IMPORTANT_RUN_LEVEL_SERVICE)
public class GrizzlyService implements RequestDispatcher, PostConstruct, PreDestroy, EventListener, FutureProvider<Result<Thread>> {

    @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
    Config config;

    @Inject
    private ServiceLocator serviceLocator;

    @Inject
    Transactions transactions;

    @Inject
    Events events;

    private static final Logger LOGGER = KernelLoggerInfo.getLogger();

    private final Collection<NetworkProxy> proxies = new LinkedBlockingQueue<NetworkProxy>();

    volatile List<Future<Result<Thread>>> futures;

    Collection<String> hosts = new ArrayList<String>();

    private final GrizzlyMonitoring monitoring;

    private static final String NETWORK_CONFIG_PREFIX = "";

    private final Set<MapperUpdateListener> mapperUpdateListeners =
            Collections.newSetFromMap(
            new ConcurrentHashMap<MapperUpdateListener, Boolean>());

    /**
     * HTTP Mapper update lock.
     */
    private final ReentrantReadWriteLock mapperLock =
            new ReentrantReadWriteLock();

    private DynamicConfigListener configListener;

    // Future to be set on server READY_EVENT
    private final FutureImpl<Boolean> serverReadyFuture =
            Futures.<Boolean>createSafeFuture();
    // Listeners to be notified once server is in READY state.
    private final Queue<Callable<Void>> serverReadyListeners =
            new ConcurrentLinkedQueue<Callable<Void>>();

    public GrizzlyService() {
        futures = new ArrayList<Future<Result<Thread>>>();
        monitoring = new GrizzlyMonitoring();
    }

    /**
     * Add the new proxy to our list of proxies.
     * @param proxy new proxy to be added
     */
    public void addNetworkProxy(NetworkProxy proxy) {
        proxies.add(proxy);
    }


    /**
     * Remove the proxy from our list of proxies by listener.
     * @param listener removes the proxy associated with the specified listener
     * @return <tt>true</tt>, if proxy removed,
     *         <tt>false</tt> if no proxy was associated with the specified listener.
     */
    public boolean removeNetworkProxy(NetworkListener listener) {
        return removeNetworkProxy(lookupNetworkProxy(listener));
    }


    /**
     * Remove the proxy from our list of proxies by id.
     * @return <tt>true</tt>, if proxy on specified port was removed,
     *         <tt>false</tt> if no proxy was associated with the port.
     */
    public boolean removeNetworkProxy(String id) {
        NetworkProxy proxy = getNetworkProxy(id);
        return removeNetworkProxy(proxy);
    }

    private NetworkProxy getNetworkProxy(String id) {
        NetworkProxy proxy = null;
        for (NetworkProxy p : proxies) {
            if (p instanceof GrizzlyProxy) {
                GrizzlyProxy grizzlyProxy = (GrizzlyProxy) p;
                if (grizzlyProxy.networkListener != null &&
                        grizzlyProxy.networkListener.getName() != null &&
                        grizzlyProxy.networkListener.getName().equals(id)) {
                    proxy = p;
                    break;
                }
            }
        }

        return proxy;
    }

    /**
     * Remove the  proxy from our list of proxies.
     * @return <tt>true</tt>, if proxy on specified port was removed,
     *         <tt>false</tt> otherwise.
     */
    public boolean removeNetworkProxy(NetworkProxy proxy) {
        if (proxy != null) {
            try {
                proxy.stop();
            } catch (IOException e) {
                LOGGER.log(Level.WARNING, KernelLoggerInfo.grizzlyStopProxy, e);
            }

            proxy.destroy();
            proxies.remove(proxy);
            return true;
        }

        return false;
    }

    /**
     * Lookup {@link GrizzlyProxy}, which corresponds to the {@link NetworkListener}.
     *
     * @param listener {@link NetworkListener}.
     * @return {@link GrizzlyProxy}, or <tt>null</tt>, if correspondent {@link GrizzlyProxy} wasn't found.
     */
    public NetworkProxy lookupNetworkProxy(NetworkListener listener) {
        int listenerPort = -1;
        InetAddress address = null;
        try {
            listenerPort = Integer.parseInt(listener.getPort());
        } catch (NumberFormatException e) {
            LOGGER.log(Level.FINE, e.toString());
        }

        try {
            address = InetAddress.getByName(listener.getAddress());
        } catch (UnknownHostException uhe) {
            LOGGER.log(Level.FINE, uhe.toString());
        }

        if (listenerPort != -1) {
            for (NetworkProxy p : proxies) {
                if (p.getPort() == listenerPort && p.getAddress().equals(address)) {
                    return p;
                }
            }
        }

        final String listenerId = listener.getName();

        for (NetworkProxy p : proxies) {
            if (p instanceof GrizzlyProxy) {
                GrizzlyProxy grizzlyProxy = (GrizzlyProxy) p;
                if (grizzlyProxy.networkListener != null &&
                        grizzlyProxy.networkListener.getName() != null &&
                        grizzlyProxy.networkListener.getName().equals(listenerId)) {
                    return p;
                }
            }
        }

        return null;

    }

    /**
     * Restart {@link NetworkListener}.
     *
     * @param networkListenerName
     * @param timeout restart timeout, if timeout value is negative - then no timeout will be applied.
     * @param timeUnit restart timeout unit
     *
     * @throws TimeoutException thrown if timeout had expired before server succeeded to restart
     * @throws IOException
     */
    public void restartNetworkListener(String networkListenerName,
            long timeout, TimeUnit timeUnit) throws IOException, TimeoutException {
        restartNetworkListener(
                config.getNetworkConfig().getNetworkListener(networkListenerName),
                timeout, timeUnit);
    }

    /**
     * Restart {@link NetworkListener}.
     *
     * @param networkListener {@link NetworkListener}
     * @param timeout restart timeout, if timeout value is negative - then no timeout will be applied.
     * @param timeUnit restart timeout unit
     *
     * @throws TimeoutException thrown if timeout had expired before server succeeded to restart
     * @throws IOException
     */
    public void restartNetworkListener(NetworkListener networkListener,
            long timeout, TimeUnit timeUnit) throws IOException, TimeoutException {

        // Restart GrizzlyProxy on the address/port
        // Address/port/id could have been changed - so try to find
        // corresponding proxy both ways
        NetworkProxy proxy = lookupNetworkProxy(networkListener);
        Map<Class<? extends HttpCodecFilter>, List<HttpProbe>> filterToProbeMapping = new HashMap<>();
        if (proxy == null) {
            proxy = getNetworkProxy(networkListener.getName());
        }
        if (proxy != null) {
            if (proxy instanceof GrizzlyProxy) {
                GrizzlyProxy grizzlyProxy = (GrizzlyProxy)proxy;
                GenericGrizzlyListener grizzlyListener = (GenericGrizzlyListener)grizzlyProxy.getUnderlyingListener();
                List<HttpCodecFilter> codecFilters = grizzlyListener.getFilters(HttpCodecFilter.class);
                if (codecFilters != null && !codecFilters.isEmpty()) {
                    for (HttpCodecFilter codecFilter : codecFilters) {
                        HttpProbe[] probes = codecFilter.getMonitoringConfig().getProbes();
                        if (probes != null) {
                            List<HttpProbe> probesForType = filterToProbeMapping.get(codecFilter.getClass());
                            if (probesForType == null) {
                                probesForType = new ArrayList<>(4);
                                filterToProbeMapping.put(codecFilter.getClass(), probesForType);
                            }
                            Collections.addAll(probesForType, probes);
                        }
                    }
                }
            }

            removeNetworkProxy(proxy);
        }
        final Future future = createNetworkProxy(networkListener);
        if (future == null) {
            LOGGER.log(Level.FINE, "Skipping proxy registration for the listener {0}",
                    networkListener.getName());
            return;
        }

        try {
            if (timeout <= 0) {
                future.get();
            } else {
                future.get(timeout, timeUnit);
            }

            NetworkProxy newNetworkProxy = getNetworkProxy(networkListener.getName());
            if (newNetworkProxy instanceof GrizzlyProxy) {
                GrizzlyProxy grizzlyProxy = (GrizzlyProxy)newNetworkProxy;
                GenericGrizzlyListener grizzlyListener = (GenericGrizzlyListener)grizzlyProxy.getUnderlyingListener();
                if (!filterToProbeMapping.isEmpty()) {
                    for (Class<? extends HttpCodecFilter> aClass : filterToProbeMapping.keySet()) {
                        List<? extends HttpCodecFilter> filters = grizzlyListener.getFilters(aClass);
                        if (filters != null && !filters.isEmpty()) {
                            if (filters.size() != 1) {
                                throw new IllegalStateException();
                            }
                            final List<HttpProbe> probes = filterToProbeMapping.get(aClass);
                            filters.get(0).getMonitoringConfig().addProbes(probes.toArray(new HttpProbe[probes.size()]));
                        }
                    }
                }
            }
        } catch (ExecutionException e) {
            throw new IOException(e.getCause());
        } catch (InterruptedException e) {
            throw new IOException(e);
        }

        registerContainerAdapters();
    }

    /**
     * Is there any {@link MapperUpdateListener} registered?
     */
    public boolean hasMapperUpdateListener(){
        return !mapperUpdateListeners.isEmpty();
    }

    /**
     * Adds {@link MapperUpdateListener} to listeners queue.
     *
     * @param listener the listener to be added.
     * @return <tt>true</tt>, if listener was successfully added,
     * or <tt>false</tt> otherwise.
     */
    public boolean addMapperUpdateListener(MapperUpdateListener listener) {
        return mapperUpdateListeners.add(listener);
    }

    /**
     * Removes {@link MapperUpdateListener} to listeners queue.
     *
     * @param listener the listener to be removed.
     * @return <tt>true</tt>, if listener was successfully removed,
     * or <tt>false</tt> otherwise.
     */
    public boolean removeMapperUpdateListener(MapperUpdateListener listener) {
        return mapperUpdateListeners.remove(listener);
    }

    /**
     * Notify all {@link MapperUpdateListener}s about update happened.
     *
     * @param networkListener {@link NetworkListener}, which {@link Mapper} got changed
     * @param mapper new {@link Mapper} value
     */
    public void notifyMapperUpdateListeners(NetworkListener networkListener,
            Mapper mapper) {
        final HttpService httpService = config.getHttpService();
        for(MapperUpdateListener listener : mapperUpdateListeners) {
            listener.update(httpService, networkListener, mapper);
        }
    }

    /**
     * Returns HTTP {@link Mapper} lock to prevent concurrent access to a
     * {@link Mapper} object.
     */
    public ReentrantReadWriteLock obtainMapperLock() {
        return mapperLock;
    }

    /**
     * Gets the logger.
     *
     * @return the logger
     */
    public Logger getLogger() {
        return LOGGER;
    }


    /**
     * Gets the habitat.
     *
     * @return the habitat
     */
    public ServiceLocator getHabitat() {
        return serviceLocator;
    }

    public GrizzlyMonitoring getMonitoring() {
        return monitoring;
    }

    /**
     * Return the {@link Future}, that might be used to monitor server startup state.
     */
    final Future<Boolean> getServerReadyFuture() {
        return serverReadyFuture;
    }

    /**
     * Add the {@link Callable} listener, which will be notified once server
     * state switches to "SERVER_READY".
     *
     * @param listener {@link Callable} listener.
     */
    final void addServerReadyListener(final Callable<Void> listener) {
        if (serverReadyFuture.isDone()) {
            try {
                listener.call();
            } catch (Exception ignored) {
            }

            return;
        }

        serverReadyListeners.add(listener);

        if (serverReadyFuture.isDone() && serverReadyListeners.remove(listener)) {
            try {
                listener.call();
            } catch (Exception ignored) {
            }
        }
    }

    /**
     * Removes the {@link Callable} listener, which will be notified once server
     * state switches to "SERVER_READY".
     *
     * @param listener {@link Callable} listener.
     */
    final boolean removeServerListener(final Callable<Void> listener) {
        return serverReadyListeners.remove(listener);
    }

    /**
     * Method is invoked each time Glassfish state changes.
     */
    @Override
    public void event(@RestrictTo(EventTypes.SERVER_READY_NAME) EventListener.Event event) {
        if (event.is(EventTypes.SERVER_READY)) {
            serverReadyFuture.result(Boolean.TRUE);

            Callable<Void> listener;
            while((listener = serverReadyListeners.poll()) != null) {
                try {
                    listener.call();
                } catch (Exception ignored) {
                }
            }
        }
    }

    /**
     * The component has been injected with any dependency and
     * will be placed into commission by the subsystem.
     */
    @Override
    public void postConstruct() {
        events.register(this);

        final NetworkConfig networkConfig = config.getNetworkConfig();
        configListener = new DynamicConfigListener(config, LOGGER);
        ObservableBean bean = (ObservableBean) ConfigSupport.getImpl(networkConfig.getNetworkListeners());
        bean.addListener(configListener);
        bean = (ObservableBean) ConfigSupport.getImpl(config.getHttpService());
        bean.addListener(configListener);
        transactions.addListenerForType(SystemProperty.class, configListener);
        configListener.setGrizzlyService(this);

        try {
            boolean isAtLeastOneProxyStarted = false;

            futures = new ArrayList<Future<Result<Thread>>>();
            for (NetworkListener listener : networkConfig.getNetworkListeners().getNetworkListener()) {
                isAtLeastOneProxyStarted |= (createNetworkProxy(listener) != null);
            }

            if (isAtLeastOneProxyStarted) {
                registerContainerAdapters();
            }
        } catch(RuntimeException e) { // So far postConstruct can not throw any other exception type
            LOGGER.log(Level.SEVERE, KernelLoggerInfo.grizzlyCantStart, e);
            for(NetworkProxy proxy : proxies) {
                try {
                    proxy.stop();
                } catch(Exception proxyStopException) {
                    LOGGER.log(Level.SEVERE, KernelLoggerInfo.grizzlyCloseException,
                            new Object[] {proxy.getPort(), proxyStopException});
                }
            }

            throw e;
        }

        registerMonitoringStatsProviders();
    }

    @Override
    public List<Future<Result<Thread>>> getFutures() {
        return futures;
    }

    /*
     * Creates a new NetworkProxy for a particular HttpListner
     * @param listener NetworkListener
     * @param networkConfig HttpService
     */
    public synchronized Future<Result<Thread>> createNetworkProxy(NetworkListener listener) {

        if (!Boolean.valueOf(listener.getEnabled())) {
            addChangeListener(listener); // in case the listener will be enabled

            LOGGER.log(Level.INFO, KernelLoggerInfo.grizzlyPortDisabled,
                    new Object[]{listener.getName(), listener.getPort()});
            return null;
        }

        // create the proxy for the port.
        GrizzlyProxy proxy = new GrizzlyProxy(this, listener);

        Future<Result<Thread>> future = null;

        try {
            proxy.initialize();

            if (!isLightWeightListener(listener)) {
                final NetworkConfig networkConfig = listener.getParent(NetworkListeners.class).getParent(NetworkConfig.class);
                // attach all virtual servers to this port
                for (VirtualServer vs : networkConfig.getParent(Config.class).getHttpService().getVirtualServer()) {
                    List<String> vsListeners =
                            StringUtils.parseStringList(vs.getNetworkListeners(), " ,");
                    if (vsListeners == null || vsListeners.isEmpty()
                            || vsListeners.contains(listener.getName())) {
                        if (!hosts.contains(vs.getId())) {
                            hosts.add(vs.getId());
                        }
                    }
                }
                addChangeListener(listener);
                addChangeListener(listener.findThreadPool());
                addChangeListener(listener.findTransport());

                final Protocol protocol = listener.findHttpProtocol();
                if (protocol != null) {
                    addChangeListener(protocol);
                    addChangeListener(protocol.getHttp());
                    addChangeListener(protocol.getHttp().getFileCache());
                    addChangeListener(protocol.getSsl());
                }
            }

            future = proxy.start();

            // add the new proxy to our list of proxies.
            proxies.add(proxy);
        } catch (Throwable e) {
            final Future<Result<Thread>> errorFuture =
                    Futures.createReadyFuture(new Result<Thread>(e));
            future = errorFuture;
        } finally {
            if (future == null) {
                final FutureImpl<Result<Thread>> errorFuture =
                        Futures.<Result<Thread>>createUnsafeFuture();
                errorFuture.result(new Result<Thread>(
                        new IllegalStateException("Unexpected error")));
                future = errorFuture;
            }

            futures.add(future);
        }

        return future;
    }

    private void addChangeListener(ConfigBeanProxy bean) {
        if(bean != null) {
            ((ObservableBean) ConfigSupport.getImpl(bean)).addListener(configListener);
        }
    }


    /*
     * Registers all proxies
     */
    void registerContainerAdapters() {
        for (org.glassfish.api.container.Adapter subAdapter :
            serviceLocator.<org.glassfish.api.container.Adapter>getAllServices(org.glassfish.api.container.Adapter.class)) {
            //@TODO change EndportRegistrationException processing if required
            try {
                if (!subAdapter.isRegistered()) {
                    registerAdapter(subAdapter);
                    subAdapter.setRegistered(true);
                }
            } catch(EndpointRegistrationException e) {
                LOGGER.log(Level.WARNING,
                        KernelLoggerInfo.grizzlyEndpointRegistration, e);
            }
        }
    }


    /**
     * The component is about to be removed from commission
     */
    @Override
    public void preDestroy() {
        for (NetworkProxy proxy : proxies) {
            try {
                proxy.stop();
            } catch (IOException e) {
                LOGGER.log(Level.WARNING, KernelLoggerInfo.grizzlyStopProxy, e);
            }
        }
        unregisterMonitoringStatsProviders();
    }

    /*
     * Registers a new endpoint (proxy implementation) for a particular
     * context-root. All request coming with the context root will be dispatched
     * to the proxy instance passed in.
     * @param contextRoot for the proxy
     * @param endpointAdapter servicing requests.
     */
    @Override
    public void registerEndpoint(String contextRoot, HttpHandler endpointAdapter,
                                 ApplicationContainer container) throws EndpointRegistrationException {

        registerEndpoint(contextRoot, endpointAdapter, container, null);
    }

    /*
     * Registers a new endpoint (proxy implementation) for a particular
     * context-root. All request coming with the context root will be dispatched
     * to the proxy instance passed in.
     * @param contextRoot for the proxy
     * @param endpointAdapter servicing requests.
     * @param application container
     * @param virtualServers comma separated list of the virtual servers
     */
    @Override
    public void registerEndpoint(String contextRoot, HttpHandler endpointAdapter,
        ApplicationContainer container, String virtualServers) throws EndpointRegistrationException {
        List<String> virtualServerList;
        if (virtualServers == null) {
            virtualServerList =
                config.getHttpService().getNonAdminVirtualServerList();
        } else{
            virtualServerList =
                StringUtils.parseStringList(virtualServers, ",");
        }
        registerEndpoint(contextRoot, virtualServerList, endpointAdapter, container);
    }


    /*
     * Registers a new endpoint (proxy implementation) for a particular
     * context-root. All request coming with the context root will be dispatched
     * to the proxy instance passed in.
     * @param contextRoot for the proxy
     * @param endpointAdapter servicing requests.
     */

    @Override
    public void registerEndpoint(String contextRoot, Collection<String> vsServers, HttpHandler endpointAdapter,
        ApplicationContainer container) throws EndpointRegistrationException {
        Collection<AddressInfo> addressInfos = getAddressInfoFromVirtualServers(vsServers);
        for (AddressInfo info : addressInfos) {
            registerEndpoint(contextRoot, info.address, info.port, vsServers, endpointAdapter, container);
        }
    }

    /**
     * Registers a new endpoint for the given context root at the given port
     * number.
     */
    @Override
    public void registerEndpoint(String contextRoot, InetAddress address, int port, Collection<String> vsServers,
        HttpHandler endpointAdapter, ApplicationContainer container) throws EndpointRegistrationException {
        for (NetworkProxy proxy : proxies) {
            if (proxy.getPort() == port && proxy.getAddress().equals(address)) {
                proxy.registerEndpoint(contextRoot, vsServers, endpointAdapter, container);
            }
        }
    }

    /**
     * Registers a new endpoint for the given context root at the given port
     * number.
     */
//    @Override
    public void registerEndpoint(final Endpoint endpoint) throws EndpointRegistrationException {
        final InetAddress address = endpoint.getAddress();
        final int port = endpoint.getPort();

        for (NetworkProxy proxy : proxies) {
            if (proxy.getPort() == port && proxy.getAddress().equals(address)) {
                proxy.registerEndpoint(endpoint);
            }
        }
    }

    /**
     * Removes the context-root from our list of endpoints.
     */
    @Override
    public void unregisterEndpoint(String contextRoot) throws EndpointRegistrationException {
        unregisterEndpoint(contextRoot, null);
    }

    /**
     * Removes the context-root from our list of endpoints.
     */
    @Override
    public void unregisterEndpoint(String contextRoot,
            ApplicationContainer app) throws EndpointRegistrationException {
        for (NetworkProxy proxy : proxies) {
            proxy.unregisterEndpoint(contextRoot, app);
        }
    }

    /**
     * Probe provider that implements each probe provider method as a
     * no-op.
     */
    @SuppressWarnings({"UnusedDeclaration"})
    public static class NoopInvocationHandler implements InvocationHandler {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) {
            // Deliberate no-op
            return null;
        }
    }

    protected void registerMonitoringStatsProviders() {
        monitoring.registerThreadPoolStatsProviderGlobal(NETWORK_CONFIG_PREFIX);
        monitoring.registerKeepAliveStatsProviderGlobal(NETWORK_CONFIG_PREFIX);
        monitoring.registerFileCacheStatsProviderGlobal(NETWORK_CONFIG_PREFIX);
        monitoring.registerConnectionQueueStatsProviderGlobal(NETWORK_CONFIG_PREFIX);
    }

    protected void unregisterMonitoringStatsProviders() {
        monitoring.unregisterThreadPoolStatsProviderGlobal(NETWORK_CONFIG_PREFIX);
        monitoring.unregisterKeepAliveStatsProviderGlobal(NETWORK_CONFIG_PREFIX);
        monitoring.unregisterFileCacheStatsProviderGlobal(NETWORK_CONFIG_PREFIX);
        monitoring.unregisterConnectionQueueStatsProviderGlobal(NETWORK_CONFIG_PREFIX);
    }

    private void registerAdapter(org.glassfish.api.container.Adapter a) throws EndpointRegistrationException {
        Endpoint endpoint = Endpoint.createEndpoint(a);
        registerEndpoint(endpoint);
    }

    // get the ports from the http listeners that are associated with
    // the virtual servers
    private List<AddressInfo> getAddressInfoFromVirtualServers(Collection<String> virtualServers) {
        List<AddressInfo> addressInfos = new ArrayList<AddressInfo>();
        List<NetworkListener> networkListenerList = config.getNetworkConfig().getNetworkListeners().getNetworkListener();

        for (String vs : virtualServers) {
            VirtualServer virtualServer =
                config.getHttpService().getVirtualServerByName(vs);
            if (virtualServer == null) {
                // non-existent virtual server
                LOGGER.log(Level.WARNING, KernelLoggerInfo.grizzlyNonExistentVS, vs);
                continue;
            }
            String vsNetworkListeners = virtualServer.getNetworkListeners();
            List<String> vsNetworkListenerList =
                StringUtils.parseStringList(vsNetworkListeners, ",");
            if (vsNetworkListenerList != null && !vsNetworkListenerList.isEmpty()) {
                for (String vsNetworkListener : vsNetworkListenerList) {
                    for (NetworkListener networkListener : networkListenerList) {
                        if (networkListener.getName().equals(vsNetworkListener) &&
                            Boolean.valueOf(networkListener.getEnabled())) {
                            addressInfos.add(new AddressInfo(networkListener.getAddress(),
                                                             networkListener.getPort()));
                            break;
                        }
                    }
                }
            }
        }
        return addressInfos;
    }

    static boolean isLightWeightListener(final NetworkListener listener) {
        return "proxy".equalsIgnoreCase(listener.getType()) ||
                "light-weight-listener".equalsIgnoreCase(listener.getProtocol());
    }

    // ---------------------------------------------------------- Nested Classes


    private static final class AddressInfo {

        private InetAddress address;
        private final int port;

        private AddressInfo(String address, String port) {
            this.port = Integer.parseInt(port);
            try {
                this.address = InetAddress.getByName(address);
            } catch (UnknownHostException ignore) {
            }
        }

    } // END AddressInfo
}
