/* * JBoss, Home of Professional Open Source. * Copyright 2014 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.undertow.server; import java.net.InetSocketAddress; import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArraySet; import io.undertow.UndertowMessages; import io.undertow.util.CopyOnWriteMap; /** * A registry of listeners, and the services that are exposed via these listeners. * * This is not used directly by Undertow, but can be used by embedding applications to * track listener metadata. * * @author Stuart Douglas */ public class ListenerRegistry { private final ConcurrentMap<String, Listener> listeners = new CopyOnWriteMap<>(); public Listener getListener(final String name) { return listeners.get(name); } public void addListener(final Listener listener) { if(listeners.putIfAbsent(listener.getName(), listener) != null) { throw UndertowMessages.MESSAGES.listenerAlreadyRegistered(listener.getName()); } } public void removeListener(final String name) { listeners.remove(name); } public static final class Listener { private final String protocol; private final String name; private final String serverName; private final InetSocketAddress bindAddress; /** * Map that can be used to store additional listener metadata */ private final Map<String, Object> contextInformation = new CopyOnWriteMap<>(); /** * Information about any HTTP upgrade handlers that are registered on this handler. */ private final Set<HttpUpgradeMetadata> httpUpgradeMetadata = new CopyOnWriteArraySet<>(); public Listener(final String protocol, final String name, final String serverName, final InetSocketAddress bindAddress) { this.protocol = protocol; this.name = name; this.serverName = serverName; this.bindAddress = bindAddress; } /** * The protocol that this listener is using */ public String getProtocol() { return protocol; } /** * The optional listener name; */ public String getName() { return name; } /** * The server name */ public String getServerName() { return serverName; } /** * The address that this listener is bound to */ public InetSocketAddress getBindAddress() { return bindAddress; } public Collection<String> getContextKeys() { return contextInformation.keySet(); } public Object removeContextInformation(final String key) { return contextInformation.remove(key); } public Object setContextInformation(final String key, final Object value) { return contextInformation.put(key, value); } public Object getContextInformation(final String key) { return contextInformation.get(key); } public void addHttpUpgradeMetadata(final HttpUpgradeMetadata upgradeMetadata) { httpUpgradeMetadata.add(upgradeMetadata); } public void removeHttpUpgradeMetadata(final HttpUpgradeMetadata upgradeMetadata) { httpUpgradeMetadata.remove(upgradeMetadata); } public Set<HttpUpgradeMetadata> getHttpUpgradeMetadata() { return Collections.unmodifiableSet(httpUpgradeMetadata); } } public static final class HttpUpgradeMetadata { private final String protocol; private final String subProtocol; private final Map<String, Object> contextInformation = new CopyOnWriteMap<>(); public HttpUpgradeMetadata(final String protocol, final String subProtocol) { this.protocol = protocol; this.subProtocol = subProtocol; } public String getProtocol() { return protocol; } public String getSubProtocol() { return subProtocol; } public Collection<String> getContextKeys() { return contextInformation.keySet(); } public Object removeContextInformation(final String key) { return contextInformation.remove(key); } public Object setContextInformation(final String key, final Object value) { return contextInformation.put(key, value); } public Object getContextInformation(final String key) { return contextInformation.get(key); } } }