Coverage Summary for Class: HostSpecifier (com.google.common.net)

Class Class, % Method, % Line, %
HostSpecifier 0% (0/1) 0% (0/7) 0% (0/32)


1 /* 2  * Copyright (C) 2009 The Guava Authors 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5  * in compliance with the License. You may obtain a copy of the License at 6  * 7  * http://www.apache.org/licenses/LICENSE-2.0 8  * 9  * Unless required by applicable law or agreed to in writing, software distributed under the License 10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11  * or implied. See the License for the specific language governing permissions and limitations under 12  * the License. 13  */ 14  15 package com.google.common.net; 16  17 import com.google.common.annotations.Beta; 18 import com.google.common.annotations.GwtIncompatible; 19 import com.google.common.base.Preconditions; 20 import java.net.InetAddress; 21 import java.text.ParseException; 22 import javax.annotation.CheckForNull; 23  24 /** 25  * A syntactically valid host specifier, suitable for use in a URI. This may be either a numeric IP 26  * address in IPv4 or IPv6 notation, or a domain name. 27  * 28  * <p>Because this class is intended to represent host specifiers which can reasonably be used in a 29  * URI, the domain name case is further restricted to include only those domain names which end in a 30  * recognized public suffix; see {@link InternetDomainName#isPublicSuffix()} for details. 31  * 32  * <p>Note that no network lookups are performed by any {@code HostSpecifier} methods. No attempt is 33  * made to verify that a provided specifier corresponds to a real or accessible host. Only syntactic 34  * and pattern-based checks are performed. 35  * 36  * <p>If you know that a given string represents a numeric IP address, use {@link InetAddresses} to 37  * obtain and manipulate a {@link java.net.InetAddress} instance from it rather than using this 38  * class. Similarly, if you know that a given string represents a domain name, use {@link 39  * InternetDomainName} rather than this class. 40  * 41  * @author Craig Berry 42  * @since 5.0 43  */ 44 @Beta 45 @GwtIncompatible 46 @ElementTypesAreNonnullByDefault 47 public final class HostSpecifier { 48  49  private final String canonicalForm; 50  51  private HostSpecifier(String canonicalForm) { 52  this.canonicalForm = canonicalForm; 53  } 54  55  /** 56  * Returns a {@code HostSpecifier} built from the provided {@code specifier}, which is already 57  * known to be valid. If the {@code specifier} might be invalid, use {@link #from(String)} 58  * instead. 59  * 60  * <p>The specifier must be in one of these formats: 61  * 62  * <ul> 63  * <li>A domain name, like {@code google.com} 64  * <li>A IPv4 address string, like {@code 127.0.0.1} 65  * <li>An IPv6 address string with or without brackets, like {@code [2001:db8::1]} or {@code 66  * 2001:db8::1} 67  * </ul> 68  * 69  * @throws IllegalArgumentException if the specifier is not valid. 70  */ 71  public static HostSpecifier fromValid(String specifier) { 72  // Verify that no port was specified, and strip optional brackets from 73  // IPv6 literals. 74  final HostAndPort parsedHost = HostAndPort.fromString(specifier); 75  Preconditions.checkArgument(!parsedHost.hasPort()); 76  final String host = parsedHost.getHost(); 77  78  // Try to interpret the specifier as an IP address. Note we build 79  // the address rather than using the .is* methods because we want to 80  // use InetAddresses.toUriString to convert the result to a string in 81  // canonical form. 82  InetAddress addr = null; 83  try { 84  addr = InetAddresses.forString(host); 85  } catch (IllegalArgumentException e) { 86  // It is not an IPv4 or IPv6 literal 87  } 88  89  if (addr != null) { 90  return new HostSpecifier(InetAddresses.toUriString(addr)); 91  } 92  93  // It is not any kind of IP address; must be a domain name or invalid. 94  95  // TODO(user): different versions of this for different factories? 96  final InternetDomainName domain = InternetDomainName.from(host); 97  98  if (domain.hasPublicSuffix()) { 99  return new HostSpecifier(domain.toString()); 100  } 101  102  throw new IllegalArgumentException( 103  "Domain name does not have a recognized public suffix: " + host); 104  } 105  106  /** 107  * Attempts to return a {@code HostSpecifier} for the given string, throwing an exception if 108  * parsing fails. Always use this method in preference to {@link #fromValid(String)} for a 109  * specifier that is not already known to be valid. 110  * 111  * @throws ParseException if the specifier is not valid. 112  */ 113  public static HostSpecifier from(String specifier) throws ParseException { 114  try { 115  return fromValid(specifier); 116  } catch (IllegalArgumentException e) { 117  // Since the IAE can originate at several different points inside 118  // fromValid(), we implement this method in terms of that one rather 119  // than the reverse. 120  121  ParseException parseException = new ParseException("Invalid host specifier: " + specifier, 0); 122  parseException.initCause(e); 123  throw parseException; 124  } 125  } 126  127  /** 128  * Determines whether {@code specifier} represents a valid {@link HostSpecifier} as described in 129  * the documentation for {@link #fromValid(String)}. 130  */ 131  public static boolean isValid(String specifier) { 132  try { 133  fromValid(specifier); 134  return true; 135  } catch (IllegalArgumentException e) { 136  return false; 137  } 138  } 139  140  @Override 141  public boolean equals(@CheckForNull Object other) { 142  if (this == other) { 143  return true; 144  } 145  146  if (other instanceof HostSpecifier) { 147  final HostSpecifier that = (HostSpecifier) other; 148  return this.canonicalForm.equals(that.canonicalForm); 149  } 150  151  return false; 152  } 153  154  @Override 155  public int hashCode() { 156  return canonicalForm.hashCode(); 157  } 158  159  /** 160  * Returns a string representation of the host specifier suitable for inclusion in a URI. If the 161  * host specifier is a domain name, the string will be normalized to all lower case. If the 162  * specifier was an IPv6 address without brackets, brackets are added so that the result will be 163  * usable in the host part of a URI. 164  */ 165  @Override 166  public String toString() { 167  return canonicalForm; 168  } 169 }