All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.netty.util.DomainNameMappingBuilder Maven / Gradle / Ivy

There is a newer version: 5.0.0.Alpha2
Show newest version
/*
 * Copyright 2016 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:
 *
 *   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.netty.util;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import static io.netty.util.internal.ObjectUtil.checkNotNull;

/**
 * Builder for immutable {@link DomainNameMapping} instances.
 *
 * @param  concrete type of value objects
 */
public final class DomainNameMappingBuilder {

    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 DomainNameMapping#map(String)} to return
     *                     when nothing matches the input
     */
    public DomainNameMappingBuilder(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 DomainNameMapping#map(String)} to return
     *                        when nothing matches the input
     */
    public DomainNameMappingBuilder(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.
     * Null values are forbidden for both hostnames and values.
     * 

* DNS wildcard is supported as hostname. * For example, you can use {@code *.netty.io} to match {@code netty.io} and {@code downloads.netty.io}. *

* * @param hostname the host name (optionally wildcard) * @param output the output value that will be returned by {@link DomainNameMapping#map(String)} * when the specified host name matches the specified input host name */ public DomainNameMappingBuilder add(String hostname, V output) { map.put(checkNotNull(hostname, "hostname"), checkNotNull(output, "output")); return this; } /** * Creates a new instance of immutable {@link DomainNameMapping} * Attempts to add new mappings to the result object will cause {@link UnsupportedOperationException} to be thrown * * @return new {@link DomainNameMapping} instance */ public DomainNameMapping build() { return new ImmutableDomainNameMapping(defaultValue, map); } /** * Immutable mapping from domain name pattern to its associated value object. * Mapping is represented by two arrays: keys and values. Key domainNamePatterns[i] is associated with values[i]. * * @param concrete type of value objects */ private static final class ImmutableDomainNameMapping extends DomainNameMapping { private static final String REPR_HEADER = "ImmutableDomainNameMapping(default: "; private static final String REPR_MAP_OPENING = ", map: {"; private static final String REPR_MAP_CLOSING = "})"; private static final int REPR_CONST_PART_LENGTH = REPR_HEADER.length() + REPR_MAP_OPENING.length() + REPR_MAP_CLOSING.length(); private final String[] domainNamePatterns; private final V[] values; private final Map map; @SuppressWarnings("unchecked") private ImmutableDomainNameMapping(V defaultValue, Map map) { super(null, defaultValue); Set> mappings = map.entrySet(); int numberOfMappings = mappings.size(); domainNamePatterns = new String[numberOfMappings]; values = (V[]) new Object[numberOfMappings]; final Map mapCopy = new LinkedHashMap(map.size()); int index = 0; for (Map.Entry mapping : mappings) { final String hostname = normalizeHostname(mapping.getKey()); final V value = mapping.getValue(); domainNamePatterns[index] = hostname; values[index] = value; mapCopy.put(hostname, value); ++index; } this.map = Collections.unmodifiableMap(mapCopy); } @Override @Deprecated public DomainNameMapping add(String hostname, V output) { throw new UnsupportedOperationException( "Immutable DomainNameMapping does not support modification after initial creation"); } @Override public V map(String hostname) { if (hostname != null) { hostname = normalizeHostname(hostname); int length = domainNamePatterns.length; for (int index = 0; index < length; ++index) { if (matches(domainNamePatterns[index], hostname)) { return values[index]; } } } return defaultValue; } @Override public Map asMap() { return map; } @Override public String toString() { String defaultValueStr = defaultValue.toString(); int numberOfMappings = domainNamePatterns.length; if (numberOfMappings == 0) { return REPR_HEADER + defaultValueStr + REPR_MAP_OPENING + REPR_MAP_CLOSING; } String pattern0 = domainNamePatterns[0]; String value0 = values[0].toString(); int oneMappingLength = pattern0.length() + value0.length() + 3; // 2 for separator ", " and 1 for '=' int estimatedBufferSize = estimateBufferSize(defaultValueStr.length(), numberOfMappings, oneMappingLength); StringBuilder sb = new StringBuilder(estimatedBufferSize) .append(REPR_HEADER).append(defaultValueStr).append(REPR_MAP_OPENING); appendMapping(sb, pattern0, value0); for (int index = 1; index < numberOfMappings; ++index) { sb.append(", "); appendMapping(sb, index); } return sb.append(REPR_MAP_CLOSING).toString(); } /** * Estimates the length of string representation of the given instance: * est = lengthOfConstantComponents + defaultValueLength + (estimatedMappingLength * numOfMappings) * 1.10 * * @param defaultValueLength length of string representation of {@link #defaultValue} * @param numberOfMappings number of mappings the given instance holds, * e.g. {@link #domainNamePatterns#length} * @param estimatedMappingLength estimated size taken by one mapping * @return estimated length of string returned by {@link #toString()} */ private static int estimateBufferSize(int defaultValueLength, int numberOfMappings, int estimatedMappingLength) { return REPR_CONST_PART_LENGTH + defaultValueLength + (int) (estimatedMappingLength * numberOfMappings * 1.10); } private StringBuilder appendMapping(StringBuilder sb, int mappingIndex) { return appendMapping(sb, domainNamePatterns[mappingIndex], values[mappingIndex].toString()); } private static StringBuilder appendMapping(StringBuilder sb, String domainNamePattern, String value) { return sb.append(domainNamePattern).append('=').append(value); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy