001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.net; 019 020import java.net.InetSocketAddress; 021import java.util.Iterator; 022import java.util.List; 023import org.apache.commons.lang3.StringUtils; 024import org.apache.yetus.audience.InterfaceAudience; 025 026import org.apache.hbase.thirdparty.com.google.common.base.Splitter; 027import org.apache.hbase.thirdparty.com.google.common.net.HostAndPort; 028 029/** 030 * An immutable type to hold a hostname and port combo, like an Endpoint or 031 * java.net.InetSocketAddress (but without danger of our calling resolve -- we do NOT want a resolve 032 * happening every time we want to hold a hostname and port combo). This class is also 033 * {@link Comparable} 034 * <p> 035 * In implementation this class is a facade over Guava's {@link HostAndPort}. We cannot have Guava 036 * classes in our API hence this Type. 037 */ 038@InterfaceAudience.Public 039public class Address implements Comparable<Address> { 040 private final HostAndPort hostAndPort; 041 042 private Address(HostAndPort hostAndPort) { 043 this.hostAndPort = hostAndPort; 044 } 045 046 public static Address fromParts(String hostname, int port) { 047 return new Address(HostAndPort.fromParts(hostname, port)); 048 } 049 050 public static Address fromString(String hostnameAndPort) { 051 return new Address(HostAndPort.fromString(hostnameAndPort)); 052 } 053 054 public static Address fromSocketAddress(InetSocketAddress addr) { 055 return Address.fromParts(addr.getHostString(), addr.getPort()); 056 } 057 058 public static InetSocketAddress toSocketAddress(Address addr) { 059 return new InetSocketAddress(addr.getHostName(), addr.getPort()); 060 } 061 062 public static InetSocketAddress[] toSocketAddress(Address[] addrs) { 063 if (addrs == null) { 064 return null; 065 } 066 InetSocketAddress[] result = new InetSocketAddress[addrs.length]; 067 for (int i = 0; i < addrs.length; i++) { 068 result[i] = toSocketAddress(addrs[i]); 069 } 070 return result; 071 } 072 073 public String getHostName() { 074 return this.hostAndPort.getHost(); 075 } 076 077 /** 078 * @deprecated Since 1.7.0, 2.4.18 and 2.5.0, will be removed in 4.0.0. Use {@link #getHostName()} 079 * instead. 080 */ 081 @Deprecated 082 public String getHostname() { 083 return this.hostAndPort.getHost(); 084 } 085 086 public int getPort() { 087 return this.hostAndPort.getPort(); 088 } 089 090 @Override 091 public String toString() { 092 return this.hostAndPort.toString(); 093 } 094 095 /** 096 * If hostname is a.b.c and the port is 123, return a:123 instead of a.b.c:123. 097 * @return if host looks like it is resolved -- not an IP -- then strip the domain portion 098 * otherwise returns same as {@link #toString()}} 099 */ 100 public String toStringWithoutDomain() { 101 String hostname = getHostName(); 102 List<String> parts = Splitter.on('.').splitToList(hostname); 103 if (parts.size() > 1) { 104 Iterator<String> i = parts.iterator(); 105 String base = i.next(); 106 while (i.hasNext()) { 107 String part = i.next(); 108 if (!StringUtils.isNumeric(part)) { 109 return Address.fromParts(base, getPort()).toString(); 110 } 111 } 112 } 113 return toString(); 114 } 115 116 @Override 117 // Don't use HostAndPort equals... It is wonky including 118 // ipv6 brackets 119 public boolean equals(Object other) { 120 if (this == other) { 121 return true; 122 } 123 if (other instanceof Address) { 124 Address that = (Address) other; 125 return this.getHostName().equals(that.getHostName()) && this.getPort() == that.getPort(); 126 } 127 return false; 128 } 129 130 @Override 131 public int hashCode() { 132 return this.getHostName().hashCode() ^ getPort(); 133 } 134 135 @Override 136 public int compareTo(Address that) { 137 int compare = this.getHostName().compareTo(that.getHostName()); 138 if (compare != 0) { 139 return compare; 140 } 141 142 return this.getPort() - that.getPort(); 143 } 144}