io.netty.util.DomainWildcardMappingBuilder Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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.netty.util;
import java.util.LinkedHashMap;
import java.util.Map;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
/**
* Builder that allows to build {@link Mapping}s that support
* DNS wildcard matching.
* @param the type of the value that we map to.
*/
public class DomainWildcardMappingBuilder {
private final V defaultValue;
private final Map map;
/**
* Constructor with default initial capacity of the map holding the mappings
*
* @param defaultValue the default value for {@link Mapping#map(Object)} )} to return
* when nothing matches the input
*/
public DomainWildcardMappingBuilder(V defaultValue) {
this(4, defaultValue);
}
/**
* Constructor with initial capacity of the map holding the mappings
*
* @param initialCapacity initial capacity for the internal map
* @param defaultValue the default value for {@link Mapping#map(Object)} to return
* when nothing matches the input
*/
public DomainWildcardMappingBuilder(int initialCapacity, V defaultValue) {
this.defaultValue = checkNotNull(defaultValue, "defaultValue");
map = new LinkedHashMap(initialCapacity);
}
/**
* Adds a mapping that maps the specified (optionally wildcard) host name to the specified output value.
* {@code null} values are forbidden for both hostnames and values.
*
* DNS wildcard is supported as hostname. The
* wildcard will only match one sub-domain deep and only when wildcard is used as the most-left label.
*
* For example:
*
*
* *.netty.io will match xyz.netty.io but NOT abc.xyz.netty.io
*
*
* @param hostname the host name (optionally wildcard)
* @param output the output value that will be returned by {@link Mapping#map(Object)}
* when the specified host name matches the specified input host name
*/
public DomainWildcardMappingBuilder add(String hostname, V output) {
map.put(normalizeHostName(hostname),
checkNotNull(output, "output"));
return this;
}
private String normalizeHostName(String hostname) {
checkNotNull(hostname, "hostname");
if (hostname.isEmpty() || hostname.charAt(0) == '.') {
throw new IllegalArgumentException("Hostname '" + hostname + "' not valid");
}
hostname = ImmutableDomainWildcardMapping.normalize(checkNotNull(hostname, "hostname"));
if (hostname.charAt(0) == '*') {
if (hostname.length() < 3 || hostname.charAt(1) != '.') {
throw new IllegalArgumentException("Wildcard Hostname '" + hostname + "'not valid");
}
return hostname.substring(1);
}
return hostname;
}
/**
* Creates a new instance of an immutable {@link Mapping}.
*
* @return new {@link Mapping} instance
*/
public Mapping build() {
return new ImmutableDomainWildcardMapping(defaultValue, map);
}
private static final class ImmutableDomainWildcardMapping implements Mapping {
private static final String REPR_HEADER = "ImmutableDomainWildcardMapping(default: ";
private static final String REPR_MAP_OPENING = ", map: ";
private static final String REPR_MAP_CLOSING = ")";
private final V defaultValue;
private final Map map;
ImmutableDomainWildcardMapping(V defaultValue, Map map) {
this.defaultValue = defaultValue;
this.map = new LinkedHashMap(map);
}
@Override
public V map(String hostname) {
if (hostname != null) {
hostname = normalize(hostname);
// Let's try an exact match first
V value = map.get(hostname);
if (value != null) {
return value;
}
// No exact match, let's try a wildcard match.
int idx = hostname.indexOf('.');
if (idx != -1) {
value = map.get(hostname.substring(idx));
if (value != null) {
return value;
}
}
}
return defaultValue;
}
@SuppressWarnings("deprecation")
static String normalize(String hostname) {
return DomainNameMapping.normalizeHostname(hostname);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(REPR_HEADER).append(defaultValue).append(REPR_MAP_OPENING).append('{');
for (Map.Entry entry : map.entrySet()) {
String hostname = entry.getKey();
if (hostname.charAt(0) == '.') {
hostname = '*' + hostname;
}
sb.append(hostname).append('=').append(entry.getValue()).append(", ");
}
sb.setLength(sb.length() - 2);
return sb.append('}').append(REPR_MAP_CLOSING).toString();
}
}
}