dubbo UrlUtils 源码

  • 2022-10-20
  • 浏览 (413)

dubbo UrlUtils 代码

文件路径:/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF 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 org.apache.dubbo.common.utils;

import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.URLStrParser;
import org.apache.dubbo.common.constants.RemotingConstants;
import org.apache.dubbo.common.url.component.ServiceConfigURL;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static java.util.Collections.emptyMap;
import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.CLASSIFIER_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PASSWORD_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PORT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.REMOVE_VALUE_PREFIX;
import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY;
import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_CATEGORY;
import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL;
import static org.apache.dubbo.common.constants.RegistryConstants.OVERRIDE_PROTOCOL;
import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PROTOCOL;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.ROUTERS_CATEGORY;
import static org.apache.dubbo.common.constants.RegistryConstants.ROUTE_PROTOCOL;
import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL;
import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_TYPE;

public class UrlUtils {

    /**
     * Forbids the instantiation.
     */
    private UrlUtils() {
        throw new UnsupportedOperationException("No instance of 'UrlUtils' for you! ");
    }

    /**
     * in the url string,mark the param begin
     */
    private static final String URL_PARAM_STARTING_SYMBOL = "?";

    public static URL parseURL(String address, Map<String, String> defaults) {
        if (StringUtils.isEmpty(address)) {
            throw new IllegalArgumentException("Address is not allowed to be empty, please re-enter.");
        }
        String url;
        if (address.contains("://") || address.contains(URL_PARAM_STARTING_SYMBOL)) {
            url = address;
        } else {
            String[] addresses = COMMA_SPLIT_PATTERN.split(address);
            url = addresses[0];
            if (addresses.length > 1) {
                StringBuilder backup = new StringBuilder();
                for (int i = 1; i < addresses.length; i++) {
                    if (i > 1) {
                        backup.append(',');
                    }
                    backup.append(addresses[i]);
                }
                url += URL_PARAM_STARTING_SYMBOL + RemotingConstants.BACKUP_KEY + "=" + backup.toString();
            }
        }
        String defaultProtocol = defaults == null ? null : defaults.get(PROTOCOL_KEY);
        if (StringUtils.isEmpty(defaultProtocol)) {
            defaultProtocol = DUBBO_PROTOCOL;
        }
        String defaultUsername = defaults == null ? null : defaults.get(USERNAME_KEY);
        String defaultPassword = defaults == null ? null : defaults.get(PASSWORD_KEY);
        int defaultPort = StringUtils.parseInteger(defaults == null ? null : defaults.get(PORT_KEY));
        String defaultPath = defaults == null ? null : defaults.get(PATH_KEY);
        Map<String, String> defaultParameters = defaults == null ? null : new HashMap<>(defaults);
        if (defaultParameters != null) {
            defaultParameters.remove(PROTOCOL_KEY);
            defaultParameters.remove(USERNAME_KEY);
            defaultParameters.remove(PASSWORD_KEY);
            defaultParameters.remove(HOST_KEY);
            defaultParameters.remove(PORT_KEY);
            defaultParameters.remove(PATH_KEY);
        }
        URL u = URL.cacheableValueOf(url);
        boolean changed = false;
        String protocol = u.getProtocol();
        String username = u.getUsername();
        String password = u.getPassword();
        String host = u.getHost();
        int port = u.getPort();
        String path = u.getPath();
        Map<String, String> parameters = new HashMap<>(u.getParameters());
        if (StringUtils.isEmpty(protocol)) {
            changed = true;
            protocol = defaultProtocol;
        }
        if (StringUtils.isEmpty(username) && StringUtils.isNotEmpty(defaultUsername)) {
            changed = true;
            username = defaultUsername;
        }
        if (StringUtils.isEmpty(password) && StringUtils.isNotEmpty(defaultPassword)) {
            changed = true;
            password = defaultPassword;
        }
        /*if (u.isAnyHost() || u.isLocalHost()) {
            changed = true;
            host = NetUtils.getLocalHost();
        }*/
        if (port <= 0) {
            if (defaultPort > 0) {
                changed = true;
                port = defaultPort;
            } else {
                changed = true;
                port = 9090;
            }
        }
        if (StringUtils.isEmpty(path)) {
            if (StringUtils.isNotEmpty(defaultPath)) {
                changed = true;
                path = defaultPath;
            }
        }
        if (defaultParameters != null && defaultParameters.size() > 0) {
            for (Map.Entry<String, String> entry : defaultParameters.entrySet()) {
                String key = entry.getKey();
                String defaultValue = entry.getValue();
                if (StringUtils.isNotEmpty(defaultValue)) {
                    String value = parameters.get(key);
                    if (StringUtils.isEmpty(value)) {
                        changed = true;
                        parameters.put(key, defaultValue);
                    }
                }
            }
        }
        if (changed) {
            u = new ServiceConfigURL(protocol, username, password, host, port, path, parameters);
        }
        return u;
    }

    public static List<URL> parseURLs(String address, Map<String, String> defaults) {
        if (StringUtils.isEmpty(address)) {
            throw new IllegalArgumentException("Address is not allowed to be empty, please re-enter.");
        }
        String[] addresses = REGISTRY_SPLIT_PATTERN.split(address);
        if (addresses == null || addresses.length == 0) {
            throw new IllegalArgumentException("Addresses is not allowed to be empty, please re-enter."); //here won't be empty
        }
        List<URL> registries = new ArrayList<URL>();
        for (String addr : addresses) {
            registries.add(parseURL(addr, defaults));
        }
        return registries;
    }

    public static Map<String, Map<String, String>> convertRegister(Map<String, Map<String, String>> register) {
        Map<String, Map<String, String>> newRegister = new HashMap<>();
        for (Map.Entry<String, Map<String, String>> entry : register.entrySet()) {
            String serviceName = entry.getKey();
            Map<String, String> serviceUrls = entry.getValue();
            if (StringUtils.isNotContains(serviceName, ':') && StringUtils.isNotContains(serviceName, '/')) {
                for (Map.Entry<String, String> entry2 : serviceUrls.entrySet()) {
                    String serviceUrl = entry2.getKey();
                    String serviceQuery = entry2.getValue();
                    Map<String, String> params = StringUtils.parseQueryString(serviceQuery);
                    String group = params.get(GROUP_KEY);
                    String version = params.get(VERSION_KEY);
                    //params.remove("group");
                    //params.remove("version");
                    String name = serviceName;
                    if (StringUtils.isNotEmpty(group)) {
                        name = group + "/" + name;
                    }
                    if (StringUtils.isNotEmpty(version)) {
                        name = name + ":" + version;
                    }
                    Map<String, String> newUrls = newRegister.computeIfAbsent(name, k -> new HashMap<>());
                    newUrls.put(serviceUrl, StringUtils.toQueryString(params));
                }
            } else {
                newRegister.put(serviceName, serviceUrls);
            }
        }
        return newRegister;
    }

    public static Map<String, String> convertSubscribe(Map<String, String> subscribe) {
        Map<String, String> newSubscribe = new HashMap<>();

        for (Map.Entry<String, String> entry : subscribe.entrySet()) {
            String serviceName = entry.getKey();
            String serviceQuery = entry.getValue();
            if (StringUtils.isNotContains(serviceName, ':') && StringUtils.isNotContains(serviceName, '/')) {
                Map<String, String> params = StringUtils.parseQueryString(serviceQuery);
                String group = params.get(GROUP_KEY);
                String version = params.get(VERSION_KEY);
                //params.remove("group");
                //params.remove("version");
                String name = serviceName;
                if (StringUtils.isNotEmpty(group)) {
                    name = group + "/" + name;
                }
                if (StringUtils.isNotEmpty(version)) {
                    name = name + ":" + version;
                }
                newSubscribe.put(name, StringUtils.toQueryString(params));
            } else {
                newSubscribe.put(serviceName, serviceQuery);
            }
        }

        return newSubscribe;
    }

    public static Map<String, Map<String, String>> revertRegister(Map<String, Map<String, String>> register) {
        Map<String, Map<String, String>> newRegister = new HashMap<>();

        for (Map.Entry<String, Map<String, String>> entry : register.entrySet()) {
            String serviceName = entry.getKey();
            Map<String, String> serviceUrls = entry.getValue();
            if (StringUtils.isContains(serviceName, ':') && StringUtils.isContains(serviceName, '/')) {
                for (Map.Entry<String, String> entry2 : serviceUrls.entrySet()) {
                    String serviceUrl = entry2.getKey();
                    String serviceQuery = entry2.getValue();
                    Map<String, String> params = StringUtils.parseQueryString(serviceQuery);
                    String name = serviceName;
                    int i = name.indexOf('/');
                    if (i >= 0) {
                        params.put(GROUP_KEY, name.substring(0, i));
                        name = name.substring(i + 1);
                    }
                    i = name.lastIndexOf(':');
                    if (i >= 0) {
                        params.put(VERSION_KEY, name.substring(i + 1));
                        name = name.substring(0, i);
                    }
                    Map<String, String> newUrls = newRegister.computeIfAbsent(name, k -> new HashMap<String, String>());
                    newUrls.put(serviceUrl, StringUtils.toQueryString(params));
                }
            } else {
                newRegister.put(serviceName, serviceUrls);
            }
        }

        return newRegister;
    }

    public static Map<String, String> revertSubscribe(Map<String, String> subscribe) {

        Map<String, String> newSubscribe = new HashMap<>();

        for (Map.Entry<String, String> entry : subscribe.entrySet()) {
            String serviceName = entry.getKey();
            String serviceQuery = entry.getValue();
            if (StringUtils.isContains(serviceName, ':') && StringUtils.isContains(serviceName, '/')) {
                Map<String, String> params = StringUtils.parseQueryString(serviceQuery);
                String name = serviceName;
                int i = name.indexOf('/');
                if (i >= 0) {
                    params.put(GROUP_KEY, name.substring(0, i));
                    name = name.substring(i + 1);
                }
                i = name.lastIndexOf(':');
                if (i >= 0) {
                    params.put(VERSION_KEY, name.substring(i + 1));
                    name = name.substring(0, i);
                }
                newSubscribe.put(name, StringUtils.toQueryString(params));
            } else {
                newSubscribe.put(serviceName, serviceQuery);
            }
        }
        return newSubscribe;
    }

    public static Map<String, Map<String, String>> revertNotify(Map<String, Map<String, String>> notify) {
        if (notify != null && notify.size() > 0) {
            Map<String, Map<String, String>> newNotify = new HashMap<>();
            for (Map.Entry<String, Map<String, String>> entry : notify.entrySet()) {
                String serviceName = entry.getKey();
                Map<String, String> serviceUrls = entry.getValue();
                if (StringUtils.isNotContains(serviceName, ':') && StringUtils.isNotContains(serviceName, '/')) {
                    if (CollectionUtils.isNotEmptyMap(serviceUrls)) {
                        for (Map.Entry<String, String> entry2 : serviceUrls.entrySet()) {
                            String url = entry2.getKey();
                            String query = entry2.getValue();
                            Map<String, String> params = StringUtils.parseQueryString(query);
                            String group = params.get(GROUP_KEY);
                            String version = params.get(VERSION_KEY);
                            // params.remove("group");
                            // params.remove("version");
                            String name = serviceName;
                            if (StringUtils.isNotEmpty(group)) {
                                name = group + "/" + name;
                            }
                            if (StringUtils.isNotEmpty(version)) {
                                name = name + ":" + version;
                            }
                            Map<String, String> newUrls = newNotify.computeIfAbsent(name, k -> new HashMap<>());
                            newUrls.put(url, StringUtils.toQueryString(params));
                        }
                    }
                } else {
                    newNotify.put(serviceName, serviceUrls);
                }
            }
            return newNotify;
        }
        return notify;
    }

    //compatible for dubbo-2.0.0
    public static List<String> revertForbid(List<String> forbid, Set<URL> subscribed) {
        if (CollectionUtils.isNotEmpty(forbid)) {
            List<String> newForbid = new ArrayList<>();
            for (String serviceName : forbid) {
                if (StringUtils.isNotContains(serviceName, ':') && StringUtils.isNotContains(serviceName, '/')) {
                    for (URL url : subscribed) {
                        if (serviceName.equals(url.getServiceInterface())) {
                            newForbid.add(url.getServiceKey());
                            break;
                        }
                    }
                } else {
                    newForbid.add(serviceName);
                }
            }
            return newForbid;
        }
        return forbid;
    }

    public static URL getEmptyUrl(String service, String category) {
        String group = null;
        String version = null;
        int i = service.indexOf('/');
        if (i > 0) {
            group = service.substring(0, i);
            service = service.substring(i + 1);
        }
        i = service.lastIndexOf(':');
        if (i > 0) {
            version = service.substring(i + 1);
            service = service.substring(0, i);
        }
        return URL.valueOf(EMPTY_PROTOCOL + "://0.0.0.0/" + service + URL_PARAM_STARTING_SYMBOL
            + CATEGORY_KEY + "=" + category
            + (group == null ? "" : "&" + GROUP_KEY + "=" + group)
            + (version == null ? "" : "&" + VERSION_KEY + "=" + version));
    }

    public static boolean isMatchCategory(String category, String categories) {
        if (categories == null || categories.length() == 0) {
            return DEFAULT_CATEGORY.equals(category);
        } else if (categories.contains(ANY_VALUE)) {
            return true;
        } else if (categories.contains(REMOVE_VALUE_PREFIX)) {
            return !categories.contains(REMOVE_VALUE_PREFIX + category);
        } else {
            return categories.contains(category);
        }
    }

    public static boolean isMatch(URL consumerUrl, URL providerUrl) {
        String consumerInterface = consumerUrl.getServiceInterface();
        String providerInterface = providerUrl.getServiceInterface();

        // FIXME accept providerUrl with '*' as interface name, after carefully thought about all possible scenarios I think it's ok to add this condition.

        // Return false if the consumer interface is not equals the provider interface,
        // except one of the interface configurations is equals '*' (i.e. any value).
        if (!(ANY_VALUE.equals(consumerInterface)
            || ANY_VALUE.equals(providerInterface)
            || StringUtils.isEquals(consumerInterface, providerInterface))) {
            return false;
        }

        // If the category of provider URL does not match the category of consumer URL.
        // Usually, the provider URL's category is empty, and the default category ('providers') is present.
        // Hence, the category of the provider URL is 'providers'.
        // Through observing of debugging process, I found that the category of the consumer URL is 'providers,configurators,routers'.
        if (!isMatchCategory(providerUrl.getCategory(DEFAULT_CATEGORY), consumerUrl.getCategory(DEFAULT_CATEGORY))) {
            return false;
        }

        // If the provider is not enabled, return false.
        if (!providerUrl.getParameter(ENABLED_KEY, true)
            && !ANY_VALUE.equals(consumerUrl.getParameter(ENABLED_KEY))) {
            return false;
        }

        // Obtain consumer's group, version and classifier.
        String consumerGroup = consumerUrl.getGroup();
        String consumerVersion = consumerUrl.getVersion();
        String consumerClassifier = consumerUrl.getParameter(CLASSIFIER_KEY, ANY_VALUE);

        // Obtain provider's group, version and classifier.
        String providerGroup = providerUrl.getGroup();
        String providerVersion = providerUrl.getVersion();
        String providerClassifier = providerUrl.getParameter(CLASSIFIER_KEY, ANY_VALUE);

        // If Group, Version, Classifier all matches, return true.
        boolean groupMatches = ANY_VALUE.equals(consumerGroup) || StringUtils.isEquals(consumerGroup, providerGroup) || StringUtils.isContains(consumerGroup, providerGroup);
        boolean versionMatches = ANY_VALUE.equals(consumerVersion) || StringUtils.isEquals(consumerVersion, providerVersion);
        boolean classifierMatches = consumerClassifier == null || ANY_VALUE.equals(consumerClassifier) || StringUtils.isEquals(consumerClassifier, providerClassifier);

        return groupMatches && versionMatches && classifierMatches;
    }

    public static boolean isMatchGlobPattern(String pattern, String value, URL param) {
        if (param != null && pattern.startsWith("$")) {
            pattern = param.getRawParameter(pattern.substring(1));
        }
        return isMatchGlobPattern(pattern, value);
    }

    public static boolean isMatchGlobPattern(String pattern, String value) {
        if ("*".equals(pattern)) {
            return true;
        }
        if (StringUtils.isEmpty(pattern) && StringUtils.isEmpty(value)) {
            return true;
        }
        if (StringUtils.isEmpty(pattern) || StringUtils.isEmpty(value)) {
            return false;
        }

        int i = pattern.lastIndexOf('*');
        // doesn't find "*"
        if (i == -1) {
            return value.equals(pattern);
        }
        // "*" is at the end
        else if (i == pattern.length() - 1) {
            return value.startsWith(pattern.substring(0, i));
        }
        // "*" is at the beginning
        else if (i == 0) {
            return value.endsWith(pattern.substring(i + 1));
        }
        // "*" is in the middle
        else {
            String prefix = pattern.substring(0, i);
            String suffix = pattern.substring(i + 1);
            return value.startsWith(prefix) && value.endsWith(suffix);
        }
    }

    public static boolean isServiceKeyMatch(URL pattern, URL value) {
        return pattern.getParameter(INTERFACE_KEY).equals(
            value.getParameter(INTERFACE_KEY))
            && isItemMatch(pattern.getGroup(),
            value.getGroup())
            && isItemMatch(pattern.getVersion(),
            value.getVersion());
    }

    public static List<URL> classifyUrls(List<URL> urls, Predicate<URL> predicate) {
        return urls.stream().filter(predicate).collect(Collectors.toList());
    }

    public static boolean isConfigurator(URL url) {
        return OVERRIDE_PROTOCOL.equals(url.getProtocol()) ||
            CONFIGURATORS_CATEGORY.equals(url.getCategory(DEFAULT_CATEGORY));
    }

    public static boolean isRoute(URL url) {
        return ROUTE_PROTOCOL.equals(url.getProtocol()) ||
            ROUTERS_CATEGORY.equals(url.getCategory(DEFAULT_CATEGORY));
    }

    public static boolean isProvider(URL url) {
        return !OVERRIDE_PROTOCOL.equals(url.getProtocol()) &&
            !ROUTE_PROTOCOL.equals(url.getProtocol()) &&
            PROVIDERS_CATEGORY.equals(url.getCategory(PROVIDERS_CATEGORY));
    }

    public static boolean isRegistry(URL url) {
        return REGISTRY_PROTOCOL.equals(url.getProtocol())
            || SERVICE_REGISTRY_PROTOCOL.equalsIgnoreCase(url.getProtocol())
            || (url.getProtocol() != null && url.getProtocol().endsWith("-registry-protocol"));
    }

    /**
     * The specified {@link URL} is service discovery registry type or not
     *
     * @param url the {@link URL} connects to the registry
     * @return If it is, return <code>true</code>, or <code>false</code>
     * @since 2.7.5
     */
    public static boolean hasServiceDiscoveryRegistryTypeKey(URL url) {
        return hasServiceDiscoveryRegistryTypeKey(url == null ? emptyMap() : url.getParameters());
    }

    public static boolean hasServiceDiscoveryRegistryProtocol(URL url) {
        return SERVICE_REGISTRY_PROTOCOL.equalsIgnoreCase(url.getProtocol());
    }

    public static boolean isServiceDiscoveryURL(URL url) {
        return hasServiceDiscoveryRegistryProtocol(url) || hasServiceDiscoveryRegistryTypeKey(url);
    }

    /**
     * The specified parameters of {@link URL} is service discovery registry type or not
     *
     * @param parameters the parameters of {@link URL} that connects to the registry
     * @return If it is, return <code>true</code>, or <code>false</code>
     * @since 2.7.5
     */
    public static boolean hasServiceDiscoveryRegistryTypeKey(Map<String, String> parameters) {
        if (CollectionUtils.isEmptyMap(parameters)) {
            return false;
        }
        return SERVICE_REGISTRY_TYPE.equals(parameters.get(REGISTRY_TYPE_KEY));
    }

    /**
     * Check if the given value matches the given pattern. The pattern supports wildcard "*".
     *
     * @param pattern pattern
     * @param value   value
     * @return true if match otherwise false
     */
    static boolean isItemMatch(String pattern, String value) {
        if (StringUtils.isEmpty(pattern)) {
            return value == null;
        } else {
            return "*".equals(pattern) || pattern.equals(value);
        }
    }

    /**
     * @param serviceKey, {group}/{interfaceName}:{version}
     * @return [group, interfaceName, version]
     */
    public static String[] parseServiceKey(String serviceKey) {
        String[] arr = new String[3];
        int i = serviceKey.indexOf('/');
        if (i > 0) {
            arr[0] = serviceKey.substring(0, i);
            serviceKey = serviceKey.substring(i + 1);
        }

        int j = serviceKey.indexOf(':');
        if (j > 0) {
            arr[2] = serviceKey.substring(j + 1);
            serviceKey = serviceKey.substring(0, j);
        }
        arr[1] = serviceKey;
        return arr;
    }

    /**
     * NOTICE: This method allocate too much objects, we can use {@link URLStrParser#parseDecodedStr(String)} instead.
     * <p>
     * Parse url string
     *
     * @param url URL string
     * @return URL instance
     * @see URL
     */
    public static URL valueOf(String url) {
        if (url == null || (url = url.trim()).length() == 0) {
            throw new IllegalArgumentException("url == null");
        }
        String protocol = null;
        String username = null;
        String password = null;
        String host = null;
        int port = 0;
        String path = null;
        Map<String, String> parameters = null;
        int i = url.indexOf('?'); // separator between body and parameters
        if (i >= 0) {
            String[] parts = url.substring(i + 1).split("&");
            parameters = new HashMap<>();
            for (String part : parts) {
                part = part.trim();
                if (part.length() > 0) {
                    int j = part.indexOf('=');
                    if (j >= 0) {
                        String key = part.substring(0, j);
                        String value = part.substring(j + 1);
                        parameters.put(key, value);
                        // compatible with lower versions registering "default." keys
                        if (key.startsWith(DEFAULT_KEY_PREFIX)) {
                            parameters.putIfAbsent(key.substring(DEFAULT_KEY_PREFIX.length()), value);
                        }
                    } else {
                        parameters.put(part, part);
                    }
                }
            }
            url = url.substring(0, i);
        }
        i = url.indexOf("://");
        if (i >= 0) {
            if (i == 0) {
                throw new IllegalStateException("url missing protocol: \"" + url + "\"");
            }
            protocol = url.substring(0, i);
            url = url.substring(i + 3);
        } else {
            // case: file:/path/to/file.txt
            i = url.indexOf(":/");
            if (i >= 0) {
                if (i == 0) {
                    throw new IllegalStateException("url missing protocol: \"" + url + "\"");
                }
                protocol = url.substring(0, i);
                url = url.substring(i + 1);
            }
        }

        i = url.indexOf('/');
        if (i >= 0) {
            path = url.substring(i + 1);
            url = url.substring(0, i);
        }
        i = url.lastIndexOf('@');
        if (i >= 0) {
            username = url.substring(0, i);
            int j = username.indexOf(':');
            if (j >= 0) {
                password = username.substring(j + 1);
                username = username.substring(0, j);
            }
            url = url.substring(i + 1);
        }
        i = url.lastIndexOf(':');
        if (i >= 0 && i < url.length() - 1) {
            if (url.lastIndexOf('%') > i) {
                // ipv6 address with scope id
                // e.g. fe80:0:0:0:894:aeec:f37d:23e1%en0
                // see https://howdoesinternetwork.com/2013/ipv6-zone-id
                // ignore
            } else {
                port = Integer.parseInt(url.substring(i + 1));
                url = url.substring(0, i);
            }
        }
        if (url.length() > 0) {
            host = url;
        }

        return new ServiceConfigURL(protocol, username, password, host, port, path, parameters);
    }

    public static boolean isConsumer(URL url) {
        return url.getProtocol().equalsIgnoreCase(CONSUMER) || url.getPort() == 0;
    }

}

相关信息

dubbo 源码目录

相关文章

dubbo AnnotationUtils 源码

dubbo ArrayUtils 源码

dubbo Assert 源码

dubbo AtomicPositiveInteger 源码

dubbo CIDRUtils 源码

dubbo CharSequenceComparator 源码

dubbo ClassHelper 源码

dubbo ClassLoaderResourceLoader 源码

dubbo ClassUtils 源码

dubbo CollectionUtils 源码

0  赞