blob: 3177ac1cebb2ff9cd0240e4a6cc13736a99cd95d [file] [log] [blame]
/*
* 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;
import org.apache.dubbo.common.url.component.ServiceConfigURL;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.model.ScopeModel;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import static org.apache.dubbo.common.constants.CommonConstants.SCOPE_MODEL;
public final class URLBuilder extends ServiceConfigURL {
private String protocol;
private String username;
private String password;
// by default, host to registry
private String host;
// by default, port to registry
private int port;
private String path;
private Map<String, String> parameters;
private Map<String, Object> attributes;
private Map<String, Map<String, String>> methodParameters;
public URLBuilder() {
protocol = null;
username = null;
password = null;
host = null;
port = 0;
path = null;
parameters = new HashMap<>();
attributes = new HashMap<>();
methodParameters = new HashMap<>();
}
public URLBuilder(String protocol, String host, int port) {
this(protocol, null, null, host, port, null, null);
}
public URLBuilder(String protocol, String host, int port, String[] pairs) {
this(protocol, null, null, host, port, null, CollectionUtils.toStringMap(pairs));
}
public URLBuilder(String protocol, String host, int port, Map<String, String> parameters) {
this(protocol, null, null, host, port, null, parameters);
}
public URLBuilder(String protocol, String host, int port, String path) {
this(protocol, null, null, host, port, path, null);
}
public URLBuilder(String protocol, String host, int port, String path, String... pairs) {
this(protocol, null, null, host, port, path, CollectionUtils.toStringMap(pairs));
}
public URLBuilder(String protocol, String host, int port, String path, Map<String, String> parameters) {
this(protocol, null, null, host, port, path, parameters);
}
public URLBuilder(String protocol,
String username,
String password,
String host,
int port,
String path,
Map<String, String> parameters) {
this(protocol, username, password, host, port, path, parameters, null);
}
public URLBuilder(String protocol,
String username,
String password,
String host,
int port,
String path,
Map<String, String> parameters,
Map<String, Object> attributes) {
this.protocol = protocol;
this.username = username;
this.password = password;
this.host = host;
this.port = port;
this.path = path;
this.parameters = parameters != null ? parameters : new HashMap<>();
this.attributes = attributes != null ? attributes : new HashMap<>();
}
public static URLBuilder from(URL url) {
String protocol = url.getProtocol();
String username = url.getUsername();
String password = url.getPassword();
String host = url.getHost();
int port = url.getPort();
String path = url.getPath();
Map<String, String> parameters = new HashMap<>(url.getParameters());
Map<String, Object> attributes = new HashMap<>(url.getAttributes());
return new URLBuilder(
protocol,
username,
password,
host,
port,
path,
parameters,
attributes);
}
public ServiceConfigURL build() {
if (StringUtils.isEmpty(username) && StringUtils.isNotEmpty(password)) {
throw new IllegalArgumentException("Invalid url, password without username!");
}
port = Math.max(port, 0);
// trim the leading "/"
int firstNonSlash = 0;
if (path != null) {
while (firstNonSlash < path.length() && path.charAt(firstNonSlash) == '/') {
firstNonSlash++;
}
if (firstNonSlash >= path.length()) {
path = "";
} else if (firstNonSlash > 0) {
path = path.substring(firstNonSlash);
}
}
return new ServiceConfigURL(protocol, username, password, host, port, path, parameters, attributes);
}
@Override
public URLBuilder putAttribute(String key, Object obj) {
attributes.put(key, obj);
return this;
}
@Override
public URLBuilder removeAttribute(String key) {
attributes.remove(key);
return this;
}
@Override
public URLBuilder setProtocol(String protocol) {
this.protocol = protocol;
return this;
}
@Override
public URLBuilder setUsername(String username) {
this.username = username;
return this;
}
@Override
public URLBuilder setPassword(String password) {
this.password = password;
return this;
}
@Override
public URLBuilder setHost(String host) {
this.host = host;
return this;
}
@Override
public URLBuilder setPort(int port) {
this.port = port;
return this;
}
@Override
public URLBuilder setAddress(String address) {
int i = address.lastIndexOf(':');
String host;
int port = this.port;
if (i >= 0) {
host = address.substring(0, i);
port = Integer.parseInt(address.substring(i + 1));
} else {
host = address;
}
this.host = host;
this.port = port;
return this;
}
@Override
public URLBuilder setPath(String path) {
this.path = path;
return this;
}
@Override
public URLBuilder setScopeModel(ScopeModel scopeModel) {
this.attributes.put(SCOPE_MODEL, scopeModel);
return this;
}
@Override
public URLBuilder addParameterAndEncoded(String key, String value) {
if (StringUtils.isEmpty(value)) {
return this;
}
return addParameter(key, URL.encode(value));
}
@Override
public URLBuilder addParameter(String key, boolean value) {
return addParameter(key, String.valueOf(value));
}
@Override
public URLBuilder addParameter(String key, char value) {
return addParameter(key, String.valueOf(value));
}
@Override
public URLBuilder addParameter(String key, byte value) {
return addParameter(key, String.valueOf(value));
}
@Override
public URLBuilder addParameter(String key, short value) {
return addParameter(key, String.valueOf(value));
}
@Override
public URLBuilder addParameter(String key, int value) {
return addParameter(key, String.valueOf(value));
}
@Override
public URLBuilder addParameter(String key, long value) {
return addParameter(key, String.valueOf(value));
}
@Override
public URLBuilder addParameter(String key, float value) {
return addParameter(key, String.valueOf(value));
}
@Override
public URLBuilder addParameter(String key, double value) {
return addParameter(key, String.valueOf(value));
}
@Override
public URLBuilder addParameter(String key, Enum<?> value) {
if (value == null) {
return this;
}
return addParameter(key, String.valueOf(value));
}
@Override
public URLBuilder addParameter(String key, Number value) {
if (value == null) {
return this;
}
return addParameter(key, String.valueOf(value));
}
@Override
public URLBuilder addParameter(String key, CharSequence value) {
if (value == null || value.length() == 0) {
return this;
}
return addParameter(key, String.valueOf(value));
}
@Override
public URLBuilder addParameter(String key, String value) {
if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
return this;
}
parameters.put(key, value);
return this;
}
public URLBuilder addMethodParameter(String method, String key, String value) {
if (StringUtils.isEmpty(method) || StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
return this;
}
URL.putMethodParameter(method, key, value, methodParameters);
return this;
}
@Override
public URLBuilder addParameterIfAbsent(String key, String value) {
if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
return this;
}
if (hasParameter(key)) {
return this;
}
parameters.put(key, value);
return this;
}
public URLBuilder addMethodParameterIfAbsent(String method, String key, String value) {
if (StringUtils.isEmpty(method) || StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
return this;
}
if (hasMethodParameter(method, key)) {
return this;
}
URL.putMethodParameter(method, key, value, methodParameters);
return this;
}
@Override
public URLBuilder addParameters(Map<String, String> parameters) {
if (CollectionUtils.isEmptyMap(parameters)) {
return this;
}
boolean hasAndEqual = true;
for (Map.Entry<String, String> entry : parameters.entrySet()) {
String oldValue = this.parameters.get(entry.getKey());
String newValue = entry.getValue();
if (!Objects.equals(oldValue, newValue)) {
hasAndEqual = false;
break;
}
}
// return immediately if there's no change
if (hasAndEqual) {
return this;
}
this.parameters.putAll(parameters);
return this;
}
public URLBuilder addMethodParameters(Map<String, Map<String, String>> methodParameters) {
if (CollectionUtils.isEmptyMap(methodParameters)) {
return this;
}
this.methodParameters.putAll(methodParameters);
return this;
}
@Override
public URLBuilder addParametersIfAbsent(Map<String, String> parameters) {
if (CollectionUtils.isEmptyMap(parameters)) {
return this;
}
for (Map.Entry<String, String> entry : parameters.entrySet()) {
this.parameters.putIfAbsent(entry.getKey(), entry.getValue());
}
return this;
}
@Override
public URLBuilder addParameters(String... pairs) {
if (pairs == null || pairs.length == 0) {
return this;
}
if (pairs.length % 2 != 0) {
throw new IllegalArgumentException("Map pairs can not be odd number.");
}
Map<String, String> map = new HashMap<>();
int len = pairs.length / 2;
for (int i = 0; i < len; i++) {
map.put(pairs[2 * i], pairs[2 * i + 1]);
}
return addParameters(map);
}
@Override
public URLBuilder addParameterString(String query) {
if (StringUtils.isEmpty(query)) {
return this;
}
return addParameters(StringUtils.parseQueryString(query));
}
@Override
public URLBuilder removeParameter(String key) {
if (StringUtils.isEmpty(key)) {
return this;
}
return removeParameters(key);
}
@Override
public URLBuilder removeParameters(Collection<String> keys) {
if (CollectionUtils.isEmpty(keys)) {
return this;
}
return removeParameters(keys.toArray(new String[0]));
}
@Override
public URLBuilder removeParameters(String... keys) {
if (keys == null || keys.length == 0) {
return this;
}
for (String key : keys) {
parameters.remove(key);
}
return this;
}
@Override
public URLBuilder clearParameters() {
parameters.clear();
return this;
}
@Override
public boolean hasParameter(String key) {
String value = getParameter(key);
return StringUtils.isNotEmpty(value);
}
@Override
public boolean hasMethodParameter(String method, String key) {
if (method == null) {
String suffix = "." + key;
for (String fullKey : parameters.keySet()) {
if (fullKey.endsWith(suffix)) {
return true;
}
}
return false;
}
if (key == null) {
String prefix = method + ".";
for (String fullKey : parameters.keySet()) {
if (fullKey.startsWith(prefix)) {
return true;
}
}
return false;
}
String value = getMethodParameter(method, key);
return value != null && value.length() > 0;
}
@Override
public String getParameter(String key) {
return parameters.get(key);
}
@Override
public String getMethodParameter(String method, String key) {
Map<String, String> keyMap = methodParameters.get(method);
String value = null;
if (keyMap != null) {
value = keyMap.get(key);
}
return value;
}
}