/* | |
* Copyright 1999-2011 Alibaba Group. | |
* | |
* 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 com.alibaba.dubbo.common.utils; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Set; | |
import com.alibaba.dubbo.common.Constants; | |
import com.alibaba.dubbo.common.URL; | |
public class UrlUtils { | |
public static URL parseURL(String address, Map<String, String> defaults) { | |
if (address == null || address.length() == 0) { | |
return null; | |
} | |
String url; | |
if (address.indexOf("://") >= 0) { | |
url = address; | |
} else { | |
String[] addresses = Constants.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 += "?" + Constants.BACKUP_KEY + "=" + backup.toString(); | |
} | |
} | |
String defaultProtocol = defaults == null ? null : defaults.get("protocol"); | |
if (defaultProtocol == null || defaultProtocol.length() == 0) { | |
defaultProtocol = "dubbo"; | |
} | |
String defaultUsername = defaults == null ? null : defaults.get("username"); | |
String defaultPassword = defaults == null ? null : defaults.get("password"); | |
int defaultPort = StringUtils.parseInteger(defaults == null ? null : defaults.get("port")); | |
String defaultPath = defaults == null ? null : defaults.get("path"); | |
Map<String, String> defaultParameters = defaults == null ? null : new HashMap<String, String>(defaults); | |
if (defaultParameters != null) { | |
defaultParameters.remove("protocol"); | |
defaultParameters.remove("username"); | |
defaultParameters.remove("password"); | |
defaultParameters.remove("host"); | |
defaultParameters.remove("port"); | |
defaultParameters.remove("path"); | |
} | |
URL u = URL.valueOf(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<String, String>(u.getParameters()); | |
if ((protocol == null || protocol.length() == 0) && defaultProtocol != null && defaultProtocol.length() > 0) { | |
changed = true; | |
protocol = defaultProtocol; | |
} | |
if ((username == null || username.length() == 0) && defaultUsername != null && defaultUsername.length() > 0) { | |
changed = true; | |
username = defaultUsername; | |
} | |
if ((password == null || password.length() == 0) && defaultPassword != null && defaultPassword.length() > 0) { | |
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 (path == null || path.length() == 0) { | |
if (defaultPath != null && defaultPath.length() > 0) { | |
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 (defaultValue != null && defaultValue.length() > 0) { | |
String value = parameters.get(key); | |
if (value == null || value.length() == 0) { | |
changed = true; | |
parameters.put(key, defaultValue); | |
} | |
} | |
} | |
} | |
if (changed) { | |
u = new URL(protocol, username, password, host, port, path, parameters); | |
} | |
return u; | |
} | |
public static List<URL> parseURLs(String address, Map<String, String> defaults) { | |
if (address == null || address.length() == 0) { | |
return null; | |
} | |
String[] addresses = Constants.REGISTRY_SPLIT_PATTERN.split(address); | |
if (addresses == null || addresses.length == 0) { | |
return null; //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<String, Map<String, String>>(); | |
for (Map.Entry<String, Map<String, String>> entry : register.entrySet()) { | |
String serviceName = entry.getKey(); | |
Map<String, String> serviceUrls = entry.getValue(); | |
if (!serviceName.contains(":") && !serviceName.contains("/")) { | |
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"); | |
String version = params.get("version"); | |
//params.remove("group"); | |
//params.remove("version"); | |
String name = serviceName; | |
if (group != null && group.length() > 0) { | |
name = group + "/" + name; | |
} | |
if (version != null && version.length() > 0) { | |
name = name + ":" + version; | |
} | |
Map<String, String> newUrls = newRegister.get(name); | |
if (newUrls == null) { | |
newUrls = new HashMap<String, String>(); | |
newRegister.put(name, newUrls); | |
} | |
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<String, String>(); | |
for (Map.Entry<String, String> entry : subscribe.entrySet()) { | |
String serviceName = entry.getKey(); | |
String serviceQuery = entry.getValue(); | |
if (!serviceName.contains(":") && !serviceName.contains("/")) { | |
Map<String, String> params = StringUtils.parseQueryString(serviceQuery); | |
String group = params.get("group"); | |
String version = params.get("version"); | |
//params.remove("group"); | |
//params.remove("version"); | |
String name = serviceName; | |
if (group != null && group.length() > 0) { | |
name = group + "/" + name; | |
} | |
if (version != null && version.length() > 0) { | |
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<String, Map<String, String>>(); | |
for (Map.Entry<String, Map<String, String>> entry : register.entrySet()) { | |
String serviceName = entry.getKey(); | |
Map<String, String> serviceUrls = entry.getValue(); | |
if (serviceName.contains(":") || serviceName.contains("/")) { | |
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", name.substring(0, i)); | |
name = name.substring(i + 1); | |
} | |
i = name.lastIndexOf(':'); | |
if (i >= 0) { | |
params.put("version", name.substring(i + 1)); | |
name = name.substring(0, i); | |
} | |
Map<String, String> newUrls = newRegister.get(name); | |
if (newUrls == null) { | |
newUrls = new HashMap<String, String>(); | |
newRegister.put(name, newUrls); | |
} | |
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<String, String>(); | |
for (Map.Entry<String, String> entry : subscribe.entrySet()) { | |
String serviceName = entry.getKey(); | |
String serviceQuery = entry.getValue(); | |
if (serviceName.contains(":") || serviceName.contains("/")) { | |
Map<String, String> params = StringUtils.parseQueryString(serviceQuery); | |
String name = serviceName; | |
int i = name.indexOf('/'); | |
if (i >= 0) { | |
params.put("group", name.substring(0, i)); | |
name = name.substring(i + 1); | |
} | |
i = name.lastIndexOf(':'); | |
if (i >= 0) { | |
params.put("version", 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<String, Map<String, String>>(); | |
for (Map.Entry<String, Map<String, String>> entry : notify.entrySet()) { | |
String serviceName = entry.getKey(); | |
Map<String, String> serviceUrls = entry.getValue(); | |
if (!serviceName.contains(":") && !serviceName.contains("/")) { | |
if (serviceUrls != null && serviceUrls.size() > 0) { | |
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"); | |
String version = params.get("version"); | |
// params.remove("group"); | |
// params.remove("version"); | |
String name = serviceName; | |
if (group != null && group.length() > 0) { | |
name = group + "/" + name; | |
} | |
if (version != null && version.length() > 0) { | |
name = name + ":" + version; | |
} | |
Map<String, String> newUrls = newNotify.get(name); | |
if (newUrls == null) { | |
newUrls = new HashMap<String, String>(); | |
newNotify.put(name, newUrls); | |
} | |
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 (forbid != null && forbid.size() > 0) { | |
List<String> newForbid = new ArrayList<String>(); | |
for (String serviceName : forbid) { | |
if (! serviceName.contains(":") && ! serviceName.contains("/")) { | |
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(Constants.EMPTY_PROTOCOL + "://0.0.0.0/" + service + "?" | |
+ Constants.CATEGORY_KEY + "=" + category | |
+ (group == null ? "" : "&" + Constants.GROUP_KEY + "=" + group) | |
+ (version == null ? "" : "&" + Constants.VERSION_KEY + "=" + version)); | |
} | |
public static boolean isMatchCategory(String category, String categories) { | |
if (categories == null || categories.length() == 0) { | |
return Constants.DEFAULT_CATEGORY.equals(category); | |
} else if (categories.contains(Constants.ANY_VALUE)) { | |
return true; | |
} else if (categories.contains(Constants.REMOVE_VALUE_PREFIX)) { | |
return ! categories.contains(Constants.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(); | |
if( ! (Constants.ANY_VALUE.equals(consumerInterface) || StringUtils.isEquals(consumerInterface, providerInterface)) ) return false; | |
if (! isMatchCategory(providerUrl.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY), | |
consumerUrl.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY))) { | |
return false; | |
} | |
if (! providerUrl.getParameter(Constants.ENABLED_KEY, true) | |
&& ! Constants.ANY_VALUE.equals(consumerUrl.getParameter(Constants.ENABLED_KEY))) { | |
return false; | |
} | |
String consumerGroup = consumerUrl.getParameter(Constants.GROUP_KEY); | |
String consumerVersion = consumerUrl.getParameter(Constants.VERSION_KEY); | |
String consumerClassifier = consumerUrl.getParameter(Constants.CLASSIFIER_KEY, Constants.ANY_VALUE); | |
String providerGroup = providerUrl.getParameter(Constants.GROUP_KEY); | |
String providerVersion = providerUrl.getParameter(Constants.VERSION_KEY); | |
String providerClassifier = providerUrl.getParameter(Constants.CLASSIFIER_KEY, Constants.ANY_VALUE); | |
return (Constants.ANY_VALUE.equals(consumerGroup) || StringUtils.isEquals(consumerGroup, providerGroup) || StringUtils.isContains(consumerGroup, providerGroup)) | |
&& (Constants.ANY_VALUE.equals(consumerVersion) || StringUtils.isEquals(consumerVersion, providerVersion)) | |
&& (consumerClassifier == null || Constants.ANY_VALUE.equals(consumerClassifier) || StringUtils.isEquals(consumerClassifier, providerClassifier)); | |
} | |
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((pattern == null || pattern.length() == 0) | |
&& (value == null || value.length() == 0)) | |
return true; | |
if((pattern == null || pattern.length() == 0) | |
|| (value == null || value.length() == 0)) | |
return false; | |
int i = pattern.lastIndexOf('*'); | |
// 没有找到星号 | |
if(i == -1) { | |
return value.equals(pattern); | |
} | |
// 星号在末尾 | |
else if (i == pattern.length() - 1) { | |
return value.startsWith(pattern.substring(0, i)); | |
} | |
// 星号的开头 | |
else if (i == 0) { | |
return value.endsWith(pattern.substring(i + 1)); | |
} | |
// 星号的字符串的中间 | |
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(Constants.INTERFACE_KEY).equals( | |
value.getParameter(Constants.INTERFACE_KEY)) | |
&& isItemMatch(pattern.getParameter(Constants.GROUP_KEY), | |
value.getParameter(Constants.GROUP_KEY)) | |
&& isItemMatch(pattern.getParameter(Constants.VERSION_KEY), | |
value.getParameter(Constants.VERSION_KEY)); | |
} | |
/** | |
* 判断 value 是否匹配 pattern,pattern 支持 * 通配符. | |
* | |
* @param pattern pattern | |
* @param value value | |
* @return true if match otherwise false | |
*/ | |
static boolean isItemMatch(String pattern, String value) { | |
if (pattern == null) { | |
return value == null; | |
} else { | |
return "*".equals(pattern) || pattern.equals(value); | |
} | |
} | |
} |