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 Use {@link #getHostName()} instead 079 */ 080 @Deprecated 081 public String getHostname() { 082 return this.hostAndPort.getHost(); 083 } 084 085 public int getPort() { 086 return this.hostAndPort.getPort(); 087 } 088 089 @Override 090 public String toString() { 091 return this.hostAndPort.toString(); 092 } 093 094 /** 095 * If hostname is a.b.c and the port is 123, return a:123 instead of a.b.c:123. 096 * @return if host looks like it is resolved -- not an IP -- then strip the domain portion 097 * otherwise returns same as {@link #toString()}} 098 */ 099 public String toStringWithoutDomain() { 100 String hostname = getHostName(); 101 List<String> parts = Splitter.on('.').splitToList(hostname); 102 if (parts.size() > 1) { 103 Iterator<String> i = parts.iterator(); 104 String base = i.next(); 105 while (i.hasNext()) { 106 String part = i.next(); 107 if (!StringUtils.isNumeric(part)) { 108 return Address.fromParts(base, getPort()).toString(); 109 } 110 } 111 } 112 return toString(); 113 } 114 115 @Override 116 // Don't use HostAndPort equals... It is wonky including 117 // ipv6 brackets 118 public boolean equals(Object other) { 119 if (this == other) { 120 return true; 121 } 122 if (other instanceof Address) { 123 Address that = (Address) other; 124 return this.getHostName().equals(that.getHostName()) && this.getPort() == that.getPort(); 125 } 126 return false; 127 } 128 129 @Override 130 public int hashCode() { 131 return this.getHostName().hashCode() ^ getPort(); 132 } 133 134 @Override 135 public int compareTo(Address that) { 136 int compare = this.getHostName().compareTo(that.getHostName()); 137 if (compare != 0) { 138 return compare; 139 } 140 141 return this.getPort() - that.getPort(); 142 } 143}