blob: 0362af72de20db089f7fa880da0969116d8ad99f [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.url.component;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.common.utils.StringUtils;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Objects;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
public class URLAddress implements Serializable {
private static final long serialVersionUID = -1985165475234910535L;
protected String host;
protected int port;
// cache
protected transient String rawAddress;
protected transient long timestamp;
public URLAddress(String host, int port) {
this(host, port, null);
}
public URLAddress(String host, int port, String rawAddress) {
this.host = host;
port = Math.max(port, 0);
this.port = port;
this.rawAddress = rawAddress;
this.timestamp = System.currentTimeMillis();
}
public String getProtocol() {
return "";
}
public URLAddress setProtocol(String protocol) {
return this;
}
public String getUsername() {
return "";
}
public URLAddress setUsername(String username) {
return this;
}
public String getPassword() {
return "";
}
public URLAddress setPassword(String password) {
return this;
}
public String getPath() {
return "";
}
public URLAddress setPath(String path) {
return this;
}
public String getHost() {
return host;
}
public URLAddress setHost(String host) {
return new URLAddress(host, port, null);
}
public int getPort() {
return port;
}
public URLAddress setPort(int port) {
return new URLAddress(host, port, null);
}
public String getAddress() {
if (rawAddress == null) {
rawAddress = getAddress(getHost(), getPort());
}
return rawAddress;
}
public URLAddress setAddress(String host, int port) {
return new URLAddress(host, port, rawAddress);
}
public String getIp() {
return NetUtils.getIpByHost(getHost());
}
public String getRawAddress() {
return rawAddress;
}
protected String getAddress(String host, int port) {
return port <= 0 ? host : host + ':' + port;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
@Override
public int hashCode() {
return host.hashCode() * 31 + port;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof URLAddress)) return false;
URLAddress that = (URLAddress) obj;
return Objects.equals(this.getProtocol(), that.getProtocol()) &&
Objects.equals(this.getUsername(), that.getUsername()) &&
Objects.equals(this.getPassword(), that.getPassword()) &&
Objects.equals(this.getPath(), that.getPath()) &&
Objects.equals(this.getHost(), that.getHost()) &&
Objects.equals(this.getPort(), that.getPort());
}
@Override
public String toString() {
if (rawAddress != null) {
return rawAddress;
}
StringBuilder buf = new StringBuilder();
if (StringUtils.isNotEmpty(host)) {
buf.append(host);
if (port > 0) {
buf.append(':');
buf.append(port);
}
}
return buf.toString();
}
public static URLAddress parse(String rawAddress, String defaultProtocol, boolean encoded) {
try {
String decodeStr = rawAddress;
if (encoded) {
decodeStr = URLDecoder.decode(rawAddress, "UTF-8");
}
boolean isPathAddress = decodeStr.contains(PATH_SEPARATOR);
if (isPathAddress) {
return createPathURLAddress(decodeStr, rawAddress, defaultProtocol);
}
return createURLAddress(decodeStr, rawAddress, defaultProtocol);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private static URLAddress createURLAddress(String decodeStr, String rawAddress, String defaultProtocol) {
String host = null;
int port = 0;
int i = decodeStr.lastIndexOf(':');
if (i >= 0 && i < decodeStr.length() - 1) {
if (decodeStr.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(decodeStr.substring(i + 1));
host = decodeStr.substring(0, i);
}
} else {
host = decodeStr;
}
return new URLAddress(host, port, rawAddress);
}
private static PathURLAddress createPathURLAddress(String decodeStr, String rawAddress, String defaultProtocol) {
String protocol = defaultProtocol;
String path = null, username = null, password = null, host = null;
int port = 0;
int i = decodeStr.indexOf("://");
if (i >= 0) {
if (i == 0) {
throw new IllegalStateException("url missing protocol: \"" + decodeStr + "\"");
}
protocol = decodeStr.substring(0, i);
decodeStr = decodeStr.substring(i + 3);
} else {
// case: file:/path/to/file.txt
i = decodeStr.indexOf(":/");
if (i >= 0) {
if (i == 0) {
throw new IllegalStateException("url missing protocol: \"" + decodeStr + "\"");
}
protocol = decodeStr.substring(0, i);
decodeStr = decodeStr.substring(i + 1);
}
}
i = decodeStr.indexOf('/');
if (i >= 0) {
path = decodeStr.substring(i + 1);
decodeStr = decodeStr.substring(0, i);
}
i = decodeStr.lastIndexOf('@');
if (i >= 0) {
username = decodeStr.substring(0, i);
int j = username.indexOf(':');
if (j >= 0) {
password = username.substring(j + 1);
username = username.substring(0, j);
}
decodeStr = decodeStr.substring(i + 1);
}
i = decodeStr.lastIndexOf(':');
if (i >= 0 && i < decodeStr.length() - 1) {
if (decodeStr.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(decodeStr.substring(i + 1));
host = decodeStr.substring(0, i);
}
}
// check cache
protocol = URLItemCache.intern(protocol);
path = URLItemCache.checkPath(path);
return new PathURLAddress(protocol, username, password, path, host, port, rawAddress);
}
}