| /* |
| * 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<>(); |
| 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; |
| } |
| } |