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

io.streamnative.pulsar.handlers.kop.utils.NamedURIUtils Maven / Gradle / Ivy

There is a newer version: 4.0.0.4
Show newest version
/**
 * Copyright (c) 2019 - 2024 StreamNative, Inc.. All Rights Reserved.
 */
/**
 * 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.streamnative.pulsar.handlers.kop.utils;

import static java.util.Collections.singletonList;

import io.streamnative.pulsar.handlers.kop.NamedURI;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriBuilderException;
import org.apache.commons.lang3.StringUtils;

public class NamedURIUtils {

    private static final String SEPARATOR = ",";
    private static final List SUPPORTED_URI_SCHEMES = List.of("http", "https");
    private static final String DEFAULT_SCHEMA = "http";

    public static List parseListeners(
        String listenersConfig,
        String listenerProtocolMapConfig,
        int deprecatedPort) {
        List listeners = Optional.ofNullable(listenersConfig)
            .map(config -> Arrays.stream(config.split(SEPARATOR))
                .map(String::trim)
                .collect(Collectors.toList()))
            .orElse(Collections.emptyList());

        if (listeners.isEmpty() || listeners.get(0).isEmpty()) {
            listeners = singletonList(DEFAULT_SCHEMA + "://0.0.0.0:" + deprecatedPort);
        }

        List uris = listeners.stream()
            .map(listener ->
                constructNamedURI(listener, getListenerProtocolMap(listenerProtocolMapConfig)))
            .collect(Collectors.toList());
        List namedUris =
            uris.stream().filter(uri -> uri.name() != null).toList();

        if (namedUris.stream().map(NamedURI::name).distinct().count() != namedUris.size()) {
            throw new IllegalArgumentException(
                "More than one listener was specified with same name. Listener names must be unique.");
        }

        return uris;
    }

    private static NamedURI constructNamedURI(String listener, Map listenerProtocolMap) {
        URI uri;
        try {
            uri = new URI(listener);
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(
                "Listener '" + listener + "' is not a valid URI: " + e.getMessage());
        }
        if (uri.getPort() == -1) {
            throw new IllegalArgumentException(
                "Listener '" + listener + "' must specify a port.");
        }
        if (SUPPORTED_URI_SCHEMES.contains(uri.getScheme())) {
            return new NamedURI(uri, null); // unnamed.
        }
        String uriName = uri.getScheme().toLowerCase();
        String protocol = listenerProtocolMap.get(uriName);
        if (protocol == null) {
            throw new IllegalArgumentException(
                "Listener '" + uri + "' has an unsupported scheme '" + uri.getScheme() + "'");
        }
        try {
            return new NamedURI(
                UriBuilder.fromUri(listener).scheme(protocol).build(),
                uriName);
        } catch (UriBuilderException e) {
            throw new IllegalArgumentException(
                "Listener '" + listener + "' with protocol '" + protocol + "' is not a valid URI.");
        }
    }

    public static Map getListenerProtocolMap(String listenerProtocolMapConfig) {
        Map result = getMap(listenerProtocolMapConfig)
            .entrySet()
            .stream()
            .collect(Collectors.toMap(
                e -> e.getKey().toLowerCase(),
                e -> e.getValue().toLowerCase()));
        for (Map.Entry entry : result.entrySet()) {
            if (!SUPPORTED_URI_SCHEMES.contains(entry.getValue())) {
                throw new IllegalArgumentException(
                    "Listener '" + entry.getKey()
                        + "' specifies an unsupported protocol: " + entry.getValue());
            }
            if (SUPPORTED_URI_SCHEMES.contains(entry.getKey())) {
                // forbid http:https and https:http
                if (!entry.getKey().equals(entry.getValue())) {
                    throw new IllegalArgumentException(
                        "Listener name '" + entry.getKey() + "' is a supported protocol, so the "
                            + "corresponding protocol specified in "
                            + listenerProtocolMapConfig + " must be '" + entry.getKey() + "'");
                }
            }
        }
        return result;
    }

    public static Map getMap(String propertyName) {
        if (StringUtils.isEmpty(propertyName)) {
            return new HashMap<>();
        }
        String[] list = propertyName.split(SEPARATOR);
        Map map = new HashMap<>();
        for (String entry : list) {
            String[] keyValue = entry.split("\\s*:\\s*", -1);
            if (keyValue.length != 2) {
                throw new IllegalArgumentException("Map entry should have form :");
            }
            if (keyValue[0].isEmpty()) {
                throw new IllegalArgumentException(
                    "Entry '" + entry + "' in " + propertyName + " does not specify a key");
            }
            if (map.containsKey(keyValue[0])) {
                throw new IllegalArgumentException(
                    "Entry '" + keyValue[0] + "' was specified more than once in " + propertyName);
            }
            map.put(keyValue[0], keyValue[1]);
        }
        return map;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy