Home » openjdk-7 » java » net » [javadoc | source]

    1   /*
    2    * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.net;
   27   
   28   import java.util.HashMap;
   29   import java.util.LinkedHashMap;
   30   import java.util.Random;
   31   import java.util.Iterator;
   32   import java.util.LinkedList;
   33   import java.util.List;
   34   import java.util.ArrayList;
   35   import java.security.AccessController;
   36   import java.io.ObjectStreamException;
   37   import java.io.IOException;
   38   import java.io.ObjectInputStream;
   39   import sun.security.action;
   40   import sun.net.InetAddressCachePolicy;
   41   import sun.net.util.IPAddressUtil;
   42   import sun.misc.Service;
   43   import sun.net.spi.nameservice;
   44   
   45   /**
   46    * This class represents an Internet Protocol (IP) address.
   47    *
   48    * <p> An IP address is either a 32-bit or 128-bit unsigned number
   49    * used by IP, a lower-level protocol on which protocols like UDP and
   50    * TCP are built. The IP address architecture is defined by <a
   51    * href="http://www.ietf.org/rfc/rfc790.txt"><i>RFC&nbsp;790:
   52    * Assigned Numbers</i></a>, <a
   53    * href="http://www.ietf.org/rfc/rfc1918.txt"> <i>RFC&nbsp;1918:
   54    * Address Allocation for Private Internets</i></a>, <a
   55    * href="http://www.ietf.org/rfc/rfc2365.txt"><i>RFC&nbsp;2365:
   56    * Administratively Scoped IP Multicast</i></a>, and <a
   57    * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC&nbsp;2373: IP
   58    * Version 6 Addressing Architecture</i></a>. An instance of an
   59    * InetAddress consists of an IP address and possibly its
   60    * corresponding host name (depending on whether it is constructed
   61    * with a host name or whether it has already done reverse host name
   62    * resolution).
   63    *
   64    * <h4> Address types </h4>
   65    *
   66    * <blockquote><table cellspacing=2 summary="Description of unicast and multicast address types">
   67    *   <tr><th valign=top><i>unicast</i></th>
   68    *       <td>An identifier for a single interface. A packet sent to
   69    *         a unicast address is delivered to the interface identified by
   70    *         that address.
   71    *
   72    *         <p> The Unspecified Address -- Also called anylocal or wildcard
   73    *         address. It must never be assigned to any node. It indicates the
   74    *         absence of an address. One example of its use is as the target of
   75    *         bind, which allows a server to accept a client connection on any
   76    *         interface, in case the server host has multiple interfaces.
   77    *
   78    *         <p> The <i>unspecified</i> address must not be used as
   79    *         the destination address of an IP packet.
   80    *
   81    *         <p> The <i>Loopback</i> Addresses -- This is the address
   82    *         assigned to the loopback interface. Anything sent to this
   83    *         IP address loops around and becomes IP input on the local
   84    *         host. This address is often used when testing a
   85    *         client.</td></tr>
   86    *   <tr><th valign=top><i>multicast</i></th>
   87    *       <td>An identifier for a set of interfaces (typically belonging
   88    *         to different nodes). A packet sent to a multicast address is
   89    *         delivered to all interfaces identified by that address.</td></tr>
   90    * </table></blockquote>
   91    *
   92    * <h4> IP address scope </h4>
   93    *
   94    * <p> <i>Link-local</i> addresses are designed to be used for addressing
   95    * on a single link for purposes such as auto-address configuration,
   96    * neighbor discovery, or when no routers are present.
   97    *
   98    * <p> <i>Site-local</i> addresses are designed to be used for addressing
   99    * inside of a site without the need for a global prefix.
  100    *
  101    * <p> <i>Global</i> addresses are unique across the internet.
  102    *
  103    * <h4> Textual representation of IP addresses </h4>
  104    *
  105    * The textual representation of an IP address is address family specific.
  106    *
  107    * <p>
  108    *
  109    * For IPv4 address format, please refer to <A
  110    * HREF="Inet4Address.html#format">Inet4Address#format</A>; For IPv6
  111    * address format, please refer to <A
  112    * HREF="Inet6Address.html#format">Inet6Address#format</A>.
  113    *
  114    * <P>There is a <a href="doc-files/net-properties.html#Ipv4IPv6">couple of
  115    * System Properties</a> affecting how IPv4 and IPv6 addresses are used.</P>
  116    *
  117    * <h4> Host Name Resolution </h4>
  118    *
  119    * Host name-to-IP address <i>resolution</i> is accomplished through
  120    * the use of a combination of local machine configuration information
  121    * and network naming services such as the Domain Name System (DNS)
  122    * and Network Information Service(NIS). The particular naming
  123    * services(s) being used is by default the local machine configured
  124    * one. For any host name, its corresponding IP address is returned.
  125    *
  126    * <p> <i>Reverse name resolution</i> means that for any IP address,
  127    * the host associated with the IP address is returned.
  128    *
  129    * <p> The InetAddress class provides methods to resolve host names to
  130    * their IP addresses and vice versa.
  131    *
  132    * <h4> InetAddress Caching </h4>
  133    *
  134    * The InetAddress class has a cache to store successful as well as
  135    * unsuccessful host name resolutions.
  136    *
  137    * <p> By default, when a security manager is installed, in order to
  138    * protect against DNS spoofing attacks,
  139    * the result of positive host name resolutions are
  140    * cached forever. When a security manager is not installed, the default
  141    * behavior is to cache entries for a finite (implementation dependent)
  142    * period of time. The result of unsuccessful host
  143    * name resolution is cached for a very short period of time (10
  144    * seconds) to improve performance.
  145    *
  146    * <p> If the default behavior is not desired, then a Java security property
  147    * can be set to a different Time-to-live (TTL) value for positive
  148    * caching. Likewise, a system admin can configure a different
  149    * negative caching TTL value when needed.
  150    *
  151    * <p> Two Java security properties control the TTL values used for
  152    *  positive and negative host name resolution caching:
  153    *
  154    * <blockquote>
  155    * <dl>
  156    * <dt><b>networkaddress.cache.ttl</b></dt>
  157    * <dd>Indicates the caching policy for successful name lookups from
  158    * the name service. The value is specified as as integer to indicate
  159    * the number of seconds to cache the successful lookup. The default
  160    * setting is to cache for an implementation specific period of time.
  161    * <p>
  162    * A value of -1 indicates "cache forever".
  163    * </dd>
  164    * <p>
  165    * <dt><b>networkaddress.cache.negative.ttl</b> (default: 10)</dt>
  166    * <dd>Indicates the caching policy for un-successful name lookups
  167    * from the name service. The value is specified as as integer to
  168    * indicate the number of seconds to cache the failure for
  169    * un-successful lookups.
  170    * <p>
  171    * A value of 0 indicates "never cache".
  172    * A value of -1 indicates "cache forever".
  173    * </dd>
  174    * </dl>
  175    * </blockquote>
  176    *
  177    * @author  Chris Warth
  178    * @see     java.net.InetAddress#getByAddress(byte[])
  179    * @see     java.net.InetAddress#getByAddress(java.lang.String, byte[])
  180    * @see     java.net.InetAddress#getAllByName(java.lang.String)
  181    * @see     java.net.InetAddress#getByName(java.lang.String)
  182    * @see     java.net.InetAddress#getLocalHost()
  183    * @since JDK1.0
  184    */
  185   public
  186   class InetAddress implements java.io.Serializable {
  187       /**
  188        * Specify the address family: Internet Protocol, Version 4
  189        * @since 1.4
  190        */
  191       static final int IPv4 = 1;
  192   
  193       /**
  194        * Specify the address family: Internet Protocol, Version 6
  195        * @since 1.4
  196        */
  197       static final int IPv6 = 2;
  198   
  199       /* Specify address family preference */
  200       static transient boolean preferIPv6Address = false;
  201   
  202       /**
  203        * @serial
  204        */
  205       String hostName;
  206   
  207       /**
  208        * Holds a 32-bit IPv4 address.
  209        *
  210        * @serial
  211        */
  212       int address;
  213   
  214       /**
  215        * Specifies the address family type, for instance, '1' for IPv4
  216        * addresses, and '2' for IPv6 addresses.
  217        *
  218        * @serial
  219        */
  220       int family;
  221   
  222       /* Used to store the name service provider */
  223       private static List<NameService> nameServices = null;
  224   
  225       /* Used to store the best available hostname */
  226       private transient String canonicalHostName = null;
  227   
  228       /** use serialVersionUID from JDK 1.0.2 for interoperability */
  229       private static final long serialVersionUID = 3286316764910316507L;
  230   
  231       /*
  232        * Load net library into runtime, and perform initializations.
  233        */
  234       static {
  235           preferIPv6Address = java.security.AccessController.doPrivileged(
  236               new GetBooleanAction("java.net.preferIPv6Addresses")).booleanValue();
  237           AccessController.doPrivileged(new LoadLibraryAction("net"));
  238           init();
  239       }
  240   
  241       /**
  242        * Constructor for the Socket.accept() method.
  243        * This creates an empty InetAddress, which is filled in by
  244        * the accept() method.  This InetAddress, however, is not
  245        * put in the address cache, since it is not created by name.
  246        */
  247       InetAddress() {
  248       }
  249   
  250       /**
  251        * Replaces the de-serialized object with an Inet4Address object.
  252        *
  253        * @return the alternate object to the de-serialized object.
  254        *
  255        * @throws ObjectStreamException if a new object replacing this
  256        * object could not be created
  257        */
  258       private Object readResolve() throws ObjectStreamException {
  259           // will replace the deserialized 'this' object
  260           return new Inet4Address(this.hostName, this.address);
  261       }
  262   
  263       /**
  264        * Utility routine to check if the InetAddress is an
  265        * IP multicast address.
  266        * @return a <code>boolean</code> indicating if the InetAddress is
  267        * an IP multicast address
  268        * @since   JDK1.1
  269        */
  270       public boolean isMulticastAddress() {
  271           return false;
  272       }
  273   
  274       /**
  275        * Utility routine to check if the InetAddress in a wildcard address.
  276        * @return a <code>boolean</code> indicating if the Inetaddress is
  277        *         a wildcard address.
  278        * @since 1.4
  279        */
  280       public boolean isAnyLocalAddress() {
  281           return false;
  282       }
  283   
  284       /**
  285        * Utility routine to check if the InetAddress is a loopback address.
  286        *
  287        * @return a <code>boolean</code> indicating if the InetAddress is
  288        * a loopback address; or false otherwise.
  289        * @since 1.4
  290        */
  291       public boolean isLoopbackAddress() {
  292           return false;
  293       }
  294   
  295       /**
  296        * Utility routine to check if the InetAddress is an link local address.
  297        *
  298        * @return a <code>boolean</code> indicating if the InetAddress is
  299        * a link local address; or false if address is not a link local unicast address.
  300        * @since 1.4
  301        */
  302       public boolean isLinkLocalAddress() {
  303           return false;
  304       }
  305   
  306       /**
  307        * Utility routine to check if the InetAddress is a site local address.
  308        *
  309        * @return a <code>boolean</code> indicating if the InetAddress is
  310        * a site local address; or false if address is not a site local unicast address.
  311        * @since 1.4
  312        */
  313       public boolean isSiteLocalAddress() {
  314           return false;
  315       }
  316   
  317       /**
  318        * Utility routine to check if the multicast address has global scope.
  319        *
  320        * @return a <code>boolean</code> indicating if the address has
  321        *         is a multicast address of global scope, false if it is not
  322        *         of global scope or it is not a multicast address
  323        * @since 1.4
  324        */
  325       public boolean isMCGlobal() {
  326           return false;
  327       }
  328   
  329       /**
  330        * Utility routine to check if the multicast address has node scope.
  331        *
  332        * @return a <code>boolean</code> indicating if the address has
  333        *         is a multicast address of node-local scope, false if it is not
  334        *         of node-local scope or it is not a multicast address
  335        * @since 1.4
  336        */
  337       public boolean isMCNodeLocal() {
  338           return false;
  339       }
  340   
  341       /**
  342        * Utility routine to check if the multicast address has link scope.
  343        *
  344        * @return a <code>boolean</code> indicating if the address has
  345        *         is a multicast address of link-local scope, false if it is not
  346        *         of link-local scope or it is not a multicast address
  347        * @since 1.4
  348        */
  349       public boolean isMCLinkLocal() {
  350           return false;
  351       }
  352   
  353       /**
  354        * Utility routine to check if the multicast address has site scope.
  355        *
  356        * @return a <code>boolean</code> indicating if the address has
  357        *         is a multicast address of site-local scope, false if it is not
  358        *         of site-local scope or it is not a multicast address
  359        * @since 1.4
  360        */
  361       public boolean isMCSiteLocal() {
  362           return false;
  363       }
  364   
  365       /**
  366        * Utility routine to check if the multicast address has organization scope.
  367        *
  368        * @return a <code>boolean</code> indicating if the address has
  369        *         is a multicast address of organization-local scope,
  370        *         false if it is not of organization-local scope
  371        *         or it is not a multicast address
  372        * @since 1.4
  373        */
  374       public boolean isMCOrgLocal() {
  375           return false;
  376       }
  377   
  378   
  379       /**
  380        * Test whether that address is reachable. Best effort is made by the
  381        * implementation to try to reach the host, but firewalls and server
  382        * configuration may block requests resulting in a unreachable status
  383        * while some specific ports may be accessible.
  384        * A typical implementation will use ICMP ECHO REQUESTs if the
  385        * privilege can be obtained, otherwise it will try to establish
  386        * a TCP connection on port 7 (Echo) of the destination host.
  387        * <p>
  388        * The timeout value, in milliseconds, indicates the maximum amount of time
  389        * the try should take. If the operation times out before getting an
  390        * answer, the host is deemed unreachable. A negative value will result
  391        * in an IllegalArgumentException being thrown.
  392        *
  393        * @param   timeout the time, in milliseconds, before the call aborts
  394        * @return a <code>boolean</code> indicating if the address is reachable.
  395        * @throws IOException if a network error occurs
  396        * @throws  IllegalArgumentException if <code>timeout</code> is negative.
  397        * @since 1.5
  398        */
  399       public boolean isReachable(int timeout) throws IOException {
  400           return isReachable(null, 0 , timeout);
  401       }
  402   
  403       /**
  404        * Test whether that address is reachable. Best effort is made by the
  405        * implementation to try to reach the host, but firewalls and server
  406        * configuration may block requests resulting in a unreachable status
  407        * while some specific ports may be accessible.
  408        * A typical implementation will use ICMP ECHO REQUESTs if the
  409        * privilege can be obtained, otherwise it will try to establish
  410        * a TCP connection on port 7 (Echo) of the destination host.
  411        * <p>
  412        * The <code>network interface</code> and <code>ttl</code> parameters
  413        * let the caller specify which network interface the test will go through
  414        * and the maximum number of hops the packets should go through.
  415        * A negative value for the <code>ttl</code> will result in an
  416        * IllegalArgumentException being thrown.
  417        * <p>
  418        * The timeout value, in milliseconds, indicates the maximum amount of time
  419        * the try should take. If the operation times out before getting an
  420        * answer, the host is deemed unreachable. A negative value will result
  421        * in an IllegalArgumentException being thrown.
  422        *
  423        * @param   netif   the NetworkInterface through which the
  424        *                    test will be done, or null for any interface
  425        * @param   ttl     the maximum numbers of hops to try or 0 for the
  426        *                  default
  427        * @param   timeout the time, in milliseconds, before the call aborts
  428        * @throws  IllegalArgumentException if either <code>timeout</code>
  429        *                          or <code>ttl</code> are negative.
  430        * @return a <code>boolean</code>indicating if the address is reachable.
  431        * @throws IOException if a network error occurs
  432        * @since 1.5
  433        */
  434       public boolean isReachable(NetworkInterface netif, int ttl,
  435                                  int timeout) throws IOException {
  436           if (ttl < 0)
  437               throw new IllegalArgumentException("ttl can't be negative");
  438           if (timeout < 0)
  439               throw new IllegalArgumentException("timeout can't be negative");
  440   
  441           return impl.isReachable(this, timeout, netif, ttl);
  442       }
  443   
  444       /**
  445        * Gets the host name for this IP address.
  446        *
  447        * <p>If this InetAddress was created with a host name,
  448        * this host name will be remembered and returned;
  449        * otherwise, a reverse name lookup will be performed
  450        * and the result will be returned based on the system
  451        * configured name lookup service. If a lookup of the name service
  452        * is required, call
  453        * {@link #getCanonicalHostName() getCanonicalHostName}.
  454        *
  455        * <p>If there is a security manager, its
  456        * <code>checkConnect</code> method is first called
  457        * with the hostname and <code>-1</code>
  458        * as its arguments to see if the operation is allowed.
  459        * If the operation is not allowed, it will return
  460        * the textual representation of the IP address.
  461        *
  462        * @return  the host name for this IP address, or if the operation
  463        *    is not allowed by the security check, the textual
  464        *    representation of the IP address.
  465        *
  466        * @see InetAddress#getCanonicalHostName
  467        * @see SecurityManager#checkConnect
  468        */
  469       public String getHostName() {
  470           return getHostName(true);
  471       }
  472   
  473       /**
  474        * Returns the hostname for this address.
  475        * If the host is equal to null, then this address refers to any
  476        * of the local machine's available network addresses.
  477        * this is package private so SocketPermission can make calls into
  478        * here without a security check.
  479        *
  480        * <p>If there is a security manager, this method first
  481        * calls its <code>checkConnect</code> method
  482        * with the hostname and <code>-1</code>
  483        * as its arguments to see if the calling code is allowed to know
  484        * the hostname for this IP address, i.e., to connect to the host.
  485        * If the operation is not allowed, it will return
  486        * the textual representation of the IP address.
  487        *
  488        * @return  the host name for this IP address, or if the operation
  489        *    is not allowed by the security check, the textual
  490        *    representation of the IP address.
  491        *
  492        * @param check make security check if true
  493        *
  494        * @see SecurityManager#checkConnect
  495        */
  496       String getHostName(boolean check) {
  497           if (hostName == null) {
  498               hostName = InetAddress.getHostFromNameService(this, check);
  499           }
  500           return hostName;
  501       }
  502   
  503       /**
  504        * Gets the fully qualified domain name for this IP address.
  505        * Best effort method, meaning we may not be able to return
  506        * the FQDN depending on the underlying system configuration.
  507        *
  508        * <p>If there is a security manager, this method first
  509        * calls its <code>checkConnect</code> method
  510        * with the hostname and <code>-1</code>
  511        * as its arguments to see if the calling code is allowed to know
  512        * the hostname for this IP address, i.e., to connect to the host.
  513        * If the operation is not allowed, it will return
  514        * the textual representation of the IP address.
  515        *
  516        * @return  the fully qualified domain name for this IP address,
  517        *    or if the operation is not allowed by the security check,
  518        *    the textual representation of the IP address.
  519        *
  520        * @see SecurityManager#checkConnect
  521        *
  522        * @since 1.4
  523        */
  524       public String getCanonicalHostName() {
  525           if (canonicalHostName == null) {
  526               canonicalHostName =
  527                   InetAddress.getHostFromNameService(this, true);
  528           }
  529           return canonicalHostName;
  530       }
  531   
  532       /**
  533        * Returns the hostname for this address.
  534        *
  535        * <p>If there is a security manager, this method first
  536        * calls its <code>checkConnect</code> method
  537        * with the hostname and <code>-1</code>
  538        * as its arguments to see if the calling code is allowed to know
  539        * the hostname for this IP address, i.e., to connect to the host.
  540        * If the operation is not allowed, it will return
  541        * the textual representation of the IP address.
  542        *
  543        * @return  the host name for this IP address, or if the operation
  544        *    is not allowed by the security check, the textual
  545        *    representation of the IP address.
  546        *
  547        * @param check make security check if true
  548        *
  549        * @see SecurityManager#checkConnect
  550        */
  551       private static String getHostFromNameService(InetAddress addr, boolean check) {
  552           String host = null;
  553           for (NameService nameService : nameServices) {
  554               try {
  555                   // first lookup the hostname
  556                   host = nameService.getHostByAddr(addr.getAddress());
  557   
  558                   /* check to see if calling code is allowed to know
  559                    * the hostname for this IP address, ie, connect to the host
  560                    */
  561                   if (check) {
  562                       SecurityManager sec = System.getSecurityManager();
  563                       if (sec != null) {
  564                           sec.checkConnect(host, -1);
  565                       }
  566                   }
  567   
  568                   /* now get all the IP addresses for this hostname,
  569                    * and make sure one of them matches the original IP
  570                    * address. We do this to try and prevent spoofing.
  571                    */
  572   
  573                   InetAddress[] arr = InetAddress.getAllByName0(host, check);
  574                   boolean ok = false;
  575   
  576                   if(arr != null) {
  577                       for(int i = 0; !ok && i < arr.length; i++) {
  578                           ok = addr.equals(arr[i]);
  579                       }
  580                   }
  581   
  582                   //XXX: if it looks a spoof just return the address?
  583                   if (!ok) {
  584                       host = addr.getHostAddress();
  585                       return host;
  586                   }
  587   
  588                   break;
  589   
  590               } catch (SecurityException e) {
  591                   host = addr.getHostAddress();
  592                   break;
  593               } catch (UnknownHostException e) {
  594                   host = addr.getHostAddress();
  595                   // let next provider resolve the hostname
  596               }
  597           }
  598   
  599           return host;
  600       }
  601   
  602       /**
  603        * Returns the raw IP address of this <code>InetAddress</code>
  604        * object. The result is in network byte order: the highest order
  605        * byte of the address is in <code>getAddress()[0]</code>.
  606        *
  607        * @return  the raw IP address of this object.
  608        */
  609       public byte[] getAddress() {
  610           return null;
  611       }
  612   
  613       /**
  614        * Returns the IP address string in textual presentation.
  615        *
  616        * @return  the raw IP address in a string format.
  617        * @since   JDK1.0.2
  618        */
  619       public String getHostAddress() {
  620           return null;
  621        }
  622   
  623       /**
  624        * Returns a hashcode for this IP address.
  625        *
  626        * @return  a hash code value for this IP address.
  627        */
  628       public int hashCode() {
  629           return -1;
  630       }
  631   
  632       /**
  633        * Compares this object against the specified object.
  634        * The result is <code>true</code> if and only if the argument is
  635        * not <code>null</code> and it represents the same IP address as
  636        * this object.
  637        * <p>
  638        * Two instances of <code>InetAddress</code> represent the same IP
  639        * address if the length of the byte arrays returned by
  640        * <code>getAddress</code> is the same for both, and each of the
  641        * array components is the same for the byte arrays.
  642        *
  643        * @param   obj   the object to compare against.
  644        * @return  <code>true</code> if the objects are the same;
  645        *          <code>false</code> otherwise.
  646        * @see     java.net.InetAddress#getAddress()
  647        */
  648       public boolean equals(Object obj) {
  649           return false;
  650       }
  651   
  652       /**
  653        * Converts this IP address to a <code>String</code>. The
  654        * string returned is of the form: hostname / literal IP
  655        * address.
  656        *
  657        * If the host name is unresolved, no reverse name service lookup
  658        * is performed. The hostname part will be represented by an empty string.
  659        *
  660        * @return  a string representation of this IP address.
  661        */
  662       public String toString() {
  663           return ((hostName != null) ? hostName : "")
  664               + "/" + getHostAddress();
  665       }
  666   
  667       /*
  668        * Cached addresses - our own litle nis, not!
  669        */
  670       private static Cache addressCache = new Cache(Cache.Type.Positive);
  671   
  672       private static Cache negativeCache = new Cache(Cache.Type.Negative);
  673   
  674       private static boolean addressCacheInit = false;
  675   
  676       static InetAddress[]    unknown_array; // put THIS in cache
  677   
  678       static InetAddressImpl  impl;
  679   
  680       private static final HashMap<String, Void> lookupTable = new HashMap<>();
  681   
  682       /**
  683        * Represents a cache entry
  684        */
  685       static final class CacheEntry {
  686   
  687           CacheEntry(InetAddress[] addresses, long expiration) {
  688               this.addresses = addresses;
  689               this.expiration = expiration;
  690           }
  691   
  692           InetAddress[] addresses;
  693           long expiration;
  694       }
  695   
  696       /**
  697        * A cache that manages entries based on a policy specified
  698        * at creation time.
  699        */
  700       static final class Cache {
  701           private LinkedHashMap<String, CacheEntry> cache;
  702           private Type type;
  703   
  704           enum Type {Positive, Negative};
  705   
  706           /**
  707            * Create cache
  708            */
  709           public Cache(Type type) {
  710               this.type = type;
  711               cache = new LinkedHashMap<String, CacheEntry>();
  712           }
  713   
  714           private int getPolicy() {
  715               if (type == Type.Positive) {
  716                   return InetAddressCachePolicy.get();
  717               } else {
  718                   return InetAddressCachePolicy.getNegative();
  719               }
  720           }
  721   
  722           /**
  723            * Add an entry to the cache. If there's already an
  724            * entry then for this host then the entry will be
  725            * replaced.
  726            */
  727           public Cache put(String host, InetAddress[] addresses) {
  728               int policy = getPolicy();
  729               if (policy == InetAddressCachePolicy.NEVER) {
  730                   return this;
  731               }
  732   
  733               // purge any expired entries
  734   
  735               if (policy != InetAddressCachePolicy.FOREVER) {
  736   
  737                   // As we iterate in insertion order we can
  738                   // terminate when a non-expired entry is found.
  739                   LinkedList<String> expired = new LinkedList<>();
  740                   long now = System.currentTimeMillis();
  741                   for (String key : cache.keySet()) {
  742                       CacheEntry entry = cache.get(key);
  743   
  744                       if (entry.expiration >= 0 && entry.expiration < now) {
  745                           expired.add(key);
  746                       } else {
  747                           break;
  748                       }
  749                   }
  750   
  751                   for (String key : expired) {
  752                       cache.remove(key);
  753                   }
  754               }
  755   
  756               // create new entry and add it to the cache
  757               // -- as a HashMap replaces existing entries we
  758               //    don't need to explicitly check if there is
  759               //    already an entry for this host.
  760               long expiration;
  761               if (policy == InetAddressCachePolicy.FOREVER) {
  762                   expiration = -1;
  763               } else {
  764                   expiration = System.currentTimeMillis() + (policy * 1000);
  765               }
  766               CacheEntry entry = new CacheEntry(addresses, expiration);
  767               cache.put(host, entry);
  768               return this;
  769           }
  770   
  771           /**
  772            * Query the cache for the specific host. If found then
  773            * return its CacheEntry, or null if not found.
  774            */
  775           public CacheEntry get(String host) {
  776               int policy = getPolicy();
  777               if (policy == InetAddressCachePolicy.NEVER) {
  778                   return null;
  779               }
  780               CacheEntry entry = cache.get(host);
  781   
  782               // check if entry has expired
  783               if (entry != null && policy != InetAddressCachePolicy.FOREVER) {
  784                   if (entry.expiration >= 0 &&
  785                       entry.expiration < System.currentTimeMillis()) {
  786                       cache.remove(host);
  787                       entry = null;
  788                   }
  789               }
  790   
  791               return entry;
  792           }
  793       }
  794   
  795       /*
  796        * Initialize cache and insert anyLocalAddress into the
  797        * unknown array with no expiry.
  798        */
  799       private static void cacheInitIfNeeded() {
  800           assert Thread.holdsLock(addressCache);
  801           if (addressCacheInit) {
  802               return;
  803           }
  804           unknown_array = new InetAddress[1];
  805           unknown_array[0] = impl.anyLocalAddress();
  806   
  807           addressCache.put(impl.anyLocalAddress().getHostName(),
  808                            unknown_array);
  809   
  810           addressCacheInit = true;
  811       }
  812   
  813       /*
  814        * Cache the given hostname and addresses.
  815        */
  816       private static void cacheAddresses(String hostname,
  817                                          InetAddress[] addresses,
  818                                          boolean success) {
  819           hostname = hostname.toLowerCase();
  820           synchronized (addressCache) {
  821               cacheInitIfNeeded();
  822               if (success) {
  823                   addressCache.put(hostname, addresses);
  824               } else {
  825                   negativeCache.put(hostname, addresses);
  826               }
  827           }
  828       }
  829   
  830       /*
  831        * Lookup hostname in cache (positive & negative cache). If
  832        * found return addresses, null if not found.
  833        */
  834       private static InetAddress[] getCachedAddresses(String hostname) {
  835           hostname = hostname.toLowerCase();
  836   
  837           // search both positive & negative caches
  838   
  839           synchronized (addressCache) {
  840               cacheInitIfNeeded();
  841   
  842               CacheEntry entry = addressCache.get(hostname);
  843               if (entry == null) {
  844                   entry = negativeCache.get(hostname);
  845               }
  846   
  847               if (entry != null) {
  848                   return entry.addresses;
  849               }
  850           }
  851   
  852           // not found
  853           return null;
  854       }
  855   
  856       private static NameService createNSProvider(String provider) {
  857           if (provider == null)
  858               return null;
  859   
  860           NameService nameService = null;
  861           if (provider.equals("default")) {
  862               // initialize the default name service
  863               nameService = new NameService() {
  864                   public InetAddress[] lookupAllHostAddr(String host)
  865                       throws UnknownHostException {
  866                       return impl.lookupAllHostAddr(host);
  867                   }
  868                   public String getHostByAddr(byte[] addr)
  869                       throws UnknownHostException {
  870                       return impl.getHostByAddr(addr);
  871                   }
  872               };
  873           } else {
  874               final String providerName = provider;
  875               try {
  876                   nameService = java.security.AccessController.doPrivileged(
  877                       new java.security.PrivilegedExceptionAction<NameService>() {
  878                           public NameService run() {
  879                               Iterator itr = Service.providers(NameServiceDescriptor.class);
  880                               while (itr.hasNext()) {
  881                                   NameServiceDescriptor nsd
  882                                       = (NameServiceDescriptor)itr.next();
  883                                   if (providerName.
  884                                       equalsIgnoreCase(nsd.getType()+","
  885                                           +nsd.getProviderName())) {
  886                                       try {
  887                                           return nsd.createNameService();
  888                                       } catch (Exception e) {
  889                                           e.printStackTrace();
  890                                           System.err.println(
  891                                               "Cannot create name service:"
  892                                                +providerName+": " + e);
  893                                       }
  894                                   }
  895                               }
  896   
  897                               return null;
  898                           }
  899                       }
  900                   );
  901               } catch (java.security.PrivilegedActionException e) {
  902               }
  903           }
  904   
  905           return nameService;
  906       }
  907   
  908       static {
  909           // create the impl
  910           impl = InetAddressImplFactory.create();
  911   
  912           // get name service if provided and requested
  913           String provider = null;;
  914           String propPrefix = "sun.net.spi.nameservice.provider.";
  915           int n = 1;
  916           nameServices = new ArrayList<NameService>();
  917           provider = AccessController.doPrivileged(
  918                   new GetPropertyAction(propPrefix + n));
  919           while (provider != null) {
  920               NameService ns = createNSProvider(provider);
  921               if (ns != null)
  922                   nameServices.add(ns);
  923   
  924               n++;
  925               provider = AccessController.doPrivileged(
  926                       new GetPropertyAction(propPrefix + n));
  927           }
  928   
  929           // if not designate any name services provider,
  930           // create a default one
  931           if (nameServices.size() == 0) {
  932               NameService ns = createNSProvider("default");
  933               nameServices.add(ns);
  934           }
  935       }
  936   
  937       /**
  938        * Creates an InetAddress based on the provided host name and IP address.
  939        * No name service is checked for the validity of the address.
  940        *
  941        * <p> The host name can either be a machine name, such as
  942        * "<code>java.sun.com</code>", or a textual representation of its IP
  943        * address.
  944        * <p> No validity checking is done on the host name either.
  945        *
  946        * <p> If addr specifies an IPv4 address an instance of Inet4Address
  947        * will be returned; otherwise, an instance of Inet6Address
  948        * will be returned.
  949        *
  950        * <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
  951        * must be 16 bytes long
  952        *
  953        * @param host the specified host
  954        * @param addr the raw IP address in network byte order
  955        * @return  an InetAddress object created from the raw IP address.
  956        * @exception  UnknownHostException  if IP address is of illegal length
  957        * @since 1.4
  958        */
  959       public static InetAddress getByAddress(String host, byte[] addr)
  960           throws UnknownHostException {
  961           if (host != null && host.length() > 0 && host.charAt(0) == '[') {
  962               if (host.charAt(host.length()-1) == ']') {
  963                   host = host.substring(1, host.length() -1);
  964               }
  965           }
  966           if (addr != null) {
  967               if (addr.length == Inet4Address.INADDRSZ) {
  968                   return new Inet4Address(host, addr);
  969               } else if (addr.length == Inet6Address.INADDRSZ) {
  970                   byte[] newAddr
  971                       = IPAddressUtil.convertFromIPv4MappedAddress(addr);
  972                   if (newAddr != null) {
  973                       return new Inet4Address(host, newAddr);
  974                   } else {
  975                       return new Inet6Address(host, addr);
  976                   }
  977               }
  978           }
  979           throw new UnknownHostException("addr is of illegal length");
  980       }
  981   
  982   
  983       /**
  984        * Determines the IP address of a host, given the host's name.
  985        *
  986        * <p> The host name can either be a machine name, such as
  987        * "<code>java.sun.com</code>", or a textual representation of its
  988        * IP address. If a literal IP address is supplied, only the
  989        * validity of the address format is checked.
  990        *
  991        * <p> For <code>host</code> specified in literal IPv6 address,
  992        * either the form defined in RFC 2732 or the literal IPv6 address
  993        * format defined in RFC 2373 is accepted. IPv6 scoped addresses are also
  994        * supported. See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6
  995        * scoped addresses.
  996        *
  997        * <p> If the host is <tt>null</tt> then an <tt>InetAddress</tt>
  998        * representing an address of the loopback interface is returned.
  999        * See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC&nbsp;3330</a>
 1000        * section&nbsp;2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC&nbsp;2373</a>
 1001        * section&nbsp;2.5.3. </p>
 1002        *
 1003        * @param      host   the specified host, or <code>null</code>.
 1004        * @return     an IP address for the given host name.
 1005        * @exception  UnknownHostException  if no IP address for the
 1006        *               <code>host</code> could be found, or if a scope_id was specified
 1007        *               for a global IPv6 address.
 1008        * @exception  SecurityException if a security manager exists
 1009        *             and its checkConnect method doesn't allow the operation
 1010        */
 1011       public static InetAddress getByName(String host)
 1012           throws UnknownHostException {
 1013           return InetAddress.getAllByName(host)[0];
 1014       }
 1015   
 1016       // called from deployment cache manager
 1017       private static InetAddress getByName(String host, InetAddress reqAddr)
 1018           throws UnknownHostException {
 1019           return InetAddress.getAllByName(host, reqAddr)[0];
 1020       }
 1021   
 1022       /**
 1023        * Given the name of a host, returns an array of its IP addresses,
 1024        * based on the configured name service on the system.
 1025        *
 1026        * <p> The host name can either be a machine name, such as
 1027        * "<code>java.sun.com</code>", or a textual representation of its IP
 1028        * address. If a literal IP address is supplied, only the
 1029        * validity of the address format is checked.
 1030        *
 1031        * <p> For <code>host</code> specified in <i>literal IPv6 address</i>,
 1032        * either the form defined in RFC 2732 or the literal IPv6 address
 1033        * format defined in RFC 2373 is accepted. A literal IPv6 address may
 1034        * also be qualified by appending a scoped zone identifier or scope_id.
 1035        * The syntax and usage of scope_ids is described
 1036        * <a href="Inet6Address.html#scoped">here</a>.
 1037        * <p> If the host is <tt>null</tt> then an <tt>InetAddress</tt>
 1038        * representing an address of the loopback interface is returned.
 1039        * See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC&nbsp;3330</a>
 1040        * section&nbsp;2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC&nbsp;2373</a>
 1041        * section&nbsp;2.5.3. </p>
 1042        *
 1043        * <p> If there is a security manager and <code>host</code> is not
 1044        * null and <code>host.length() </code> is not equal to zero, the
 1045        * security manager's
 1046        * <code>checkConnect</code> method is called
 1047        * with the hostname and <code>-1</code>
 1048        * as its arguments to see if the operation is allowed.
 1049        *
 1050        * @param      host   the name of the host, or <code>null</code>.
 1051        * @return     an array of all the IP addresses for a given host name.
 1052        *
 1053        * @exception  UnknownHostException  if no IP address for the
 1054        *               <code>host</code> could be found, or if a scope_id was specified
 1055        *               for a global IPv6 address.
 1056        * @exception  SecurityException  if a security manager exists and its
 1057        *               <code>checkConnect</code> method doesn't allow the operation.
 1058        *
 1059        * @see SecurityManager#checkConnect
 1060        */
 1061       public static InetAddress[] getAllByName(String host)
 1062           throws UnknownHostException {
 1063           return getAllByName(host, null);
 1064       }
 1065   
 1066       private static InetAddress[] getAllByName(String host, InetAddress reqAddr)
 1067           throws UnknownHostException {
 1068   
 1069           if (host == null || host.length() == 0) {
 1070               InetAddress[] ret = new InetAddress[1];
 1071               ret[0] = impl.loopbackAddress();
 1072               return ret;
 1073           }
 1074   
 1075           boolean ipv6Expected = false;
 1076           if (host.charAt(0) == '[') {
 1077               // This is supposed to be an IPv6 literal
 1078               if (host.length() > 2 && host.charAt(host.length()-1) == ']') {
 1079                   host = host.substring(1, host.length() -1);
 1080                   ipv6Expected = true;
 1081               } else {
 1082                   // This was supposed to be a IPv6 address, but it's not!
 1083                   throw new UnknownHostException(host + ": invalid IPv6 address");
 1084               }
 1085           }
 1086   
 1087           // if host is an IP address, we won't do further lookup
 1088           if (Character.digit(host.charAt(0), 16) != -1
 1089               || (host.charAt(0) == ':')) {
 1090               byte[] addr = null;
 1091               int numericZone = -1;
 1092               String ifname = null;
 1093               // see if it is IPv4 address
 1094               addr = IPAddressUtil.textToNumericFormatV4(host);
 1095               if (addr == null) {
 1096                   // see if it is IPv6 address
 1097                   // Check if a numeric or string zone id is present
 1098                   int pos;
 1099                   if ((pos=host.indexOf ("%")) != -1) {
 1100                       numericZone = checkNumericZone (host);
 1101                       if (numericZone == -1) { /* remainder of string must be an ifname */
 1102                           ifname = host.substring (pos+1);
 1103                       }
 1104                   }
 1105                   addr = IPAddressUtil.textToNumericFormatV6(host);
 1106               } else if (ipv6Expected) {
 1107                   // Means an IPv4 litteral between brackets!
 1108                   throw new UnknownHostException("["+host+"]");
 1109               }
 1110               InetAddress[] ret = new InetAddress[1];
 1111               if(addr != null) {
 1112                   if (addr.length == Inet4Address.INADDRSZ) {
 1113                       ret[0] = new Inet4Address(null, addr);
 1114                   } else {
 1115                       if (ifname != null) {
 1116                           ret[0] = new Inet6Address(null, addr, ifname);
 1117                       } else {
 1118                           ret[0] = new Inet6Address(null, addr, numericZone);
 1119                       }
 1120                   }
 1121                   return ret;
 1122               }
 1123               } else if (ipv6Expected) {
 1124                   // We were expecting an IPv6 Litteral, but got something else
 1125                   throw new UnknownHostException("["+host+"]");
 1126               }
 1127           return getAllByName0(host, reqAddr, true);
 1128       }
 1129   
 1130       /**
 1131        * Returns the loopback address.
 1132        * <p>
 1133        * The InetAddress returned will represent the IPv4
 1134        * loopback address, 127.0.0.1, or the IPv6 loopback
 1135        * address, ::1. The IPv4 loopback address returned
 1136        * is only one of many in the form 127.*.*.*
 1137        *
 1138        * @return  the InetAddress loopback instance.
 1139        * @since 1.7
 1140        */
 1141       public static InetAddress getLoopbackAddress() {
 1142           return impl.loopbackAddress();
 1143       }
 1144   
 1145   
 1146       /**
 1147        * check if the literal address string has %nn appended
 1148        * returns -1 if not, or the numeric value otherwise.
 1149        *
 1150        * %nn may also be a string that represents the displayName of
 1151        * a currently available NetworkInterface.
 1152        */
 1153       private static int checkNumericZone (String s) throws UnknownHostException {
 1154           int percent = s.indexOf ('%');
 1155           int slen = s.length();
 1156           int digit, zone=0;
 1157           if (percent == -1) {
 1158               return -1;
 1159           }
 1160           for (int i=percent+1; i<slen; i++) {
 1161               char c = s.charAt(i);
 1162               if (c == ']') {
 1163                   if (i == percent+1) {
 1164                       /* empty per-cent field */
 1165                       return -1;
 1166                   }
 1167                   break;
 1168               }
 1169               if ((digit = Character.digit (c, 10)) < 0) {
 1170                   return -1;
 1171               }
 1172               zone = (zone * 10) + digit;
 1173           }
 1174           return zone;
 1175       }
 1176   
 1177       private static InetAddress[] getAllByName0 (String host)
 1178           throws UnknownHostException
 1179       {
 1180           return getAllByName0(host, true);
 1181       }
 1182   
 1183       /**
 1184        * package private so SocketPermission can call it
 1185        */
 1186       static InetAddress[] getAllByName0 (String host, boolean check)
 1187           throws UnknownHostException  {
 1188           return getAllByName0 (host, null, check);
 1189       }
 1190   
 1191       private static InetAddress[] getAllByName0 (String host, InetAddress reqAddr, boolean check)
 1192           throws UnknownHostException  {
 1193   
 1194           /* If it gets here it is presumed to be a hostname */
 1195           /* Cache.get can return: null, unknownAddress, or InetAddress[] */
 1196   
 1197           /* make sure the connection to the host is allowed, before we
 1198            * give out a hostname
 1199            */
 1200           if (check) {
 1201               SecurityManager security = System.getSecurityManager();
 1202               if (security != null) {
 1203                   security.checkConnect(host, -1);
 1204               }
 1205           }
 1206   
 1207           InetAddress[] addresses = getCachedAddresses(host);
 1208   
 1209           /* If no entry in cache, then do the host lookup */
 1210           if (addresses == null) {
 1211               addresses = getAddressesFromNameService(host, reqAddr);
 1212           }
 1213   
 1214           if (addresses == unknown_array)
 1215               throw new UnknownHostException(host);
 1216   
 1217           return addresses.clone();
 1218       }
 1219   
 1220       private static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr)
 1221           throws UnknownHostException
 1222       {
 1223           InetAddress[] addresses = null;
 1224           boolean success = false;
 1225           UnknownHostException ex = null;
 1226   
 1227           // Check whether the host is in the lookupTable.
 1228           // 1) If the host isn't in the lookupTable when
 1229           //    checkLookupTable() is called, checkLookupTable()
 1230           //    would add the host in the lookupTable and
 1231           //    return null. So we will do the lookup.
 1232           // 2) If the host is in the lookupTable when
 1233           //    checkLookupTable() is called, the current thread
 1234           //    would be blocked until the host is removed
 1235           //    from the lookupTable. Then this thread
 1236           //    should try to look up the addressCache.
 1237           //     i) if it found the addresses in the
 1238           //        addressCache, checkLookupTable()  would
 1239           //        return the addresses.
 1240           //     ii) if it didn't find the addresses in the
 1241           //         addressCache for any reason,
 1242           //         it should add the host in the
 1243           //         lookupTable and return null so the
 1244           //         following code would do  a lookup itself.
 1245           if ((addresses = checkLookupTable(host)) == null) {
 1246               try {
 1247                   // This is the first thread which looks up the addresses
 1248                   // this host or the cache entry for this host has been
 1249                   // expired so this thread should do the lookup.
 1250                   for (NameService nameService : nameServices) {
 1251                       try {
 1252                           /*
 1253                            * Do not put the call to lookup() inside the
 1254                            * constructor.  if you do you will still be
 1255                            * allocating space when the lookup fails.
 1256                            */
 1257   
 1258                           addresses = nameService.lookupAllHostAddr(host);
 1259                           success = true;
 1260                           break;
 1261                       } catch (UnknownHostException uhe) {
 1262                           if (host.equalsIgnoreCase("localhost")) {
 1263                               InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
 1264                               addresses = local;
 1265                               success = true;
 1266                               break;
 1267                           }
 1268                           else {
 1269                               addresses = unknown_array;
 1270                               success = false;
 1271                               ex = uhe;
 1272                           }
 1273                       }
 1274                   }
 1275   
 1276                   // More to do?
 1277                   if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) {
 1278                       // Find it?
 1279                       int i = 1;
 1280                       for (; i < addresses.length; i++) {
 1281                           if (addresses[i].equals(reqAddr)) {
 1282                               break;
 1283                           }
 1284                       }
 1285                       // Rotate
 1286                       if (i < addresses.length) {
 1287                           InetAddress tmp, tmp2 = reqAddr;
 1288                           for (int j = 0; j < i; j++) {
 1289                               tmp = addresses[j];
 1290                               addresses[j] = tmp2;
 1291                               tmp2 = tmp;
 1292                           }
 1293                           addresses[i] = tmp2;
 1294                       }
 1295                   }
 1296                   // Cache the address.
 1297                   cacheAddresses(host, addresses, success);
 1298   
 1299                   if (!success && ex != null)
 1300                       throw ex;
 1301   
 1302               } finally {
 1303                   // Delete host from the lookupTable and notify
 1304                   // all threads waiting on the lookupTable monitor.
 1305                   updateLookupTable(host);
 1306               }
 1307           }
 1308   
 1309           return addresses;
 1310       }
 1311   
 1312   
 1313       private static InetAddress[] checkLookupTable(String host) {
 1314           synchronized (lookupTable) {
 1315               // If the host isn't in the lookupTable, add it in the
 1316               // lookuptable and return null. The caller should do
 1317               // the lookup.
 1318               if (lookupTable.containsKey(host) == false) {
 1319                   lookupTable.put(host, null);
 1320                   return null;
 1321               }
 1322   
 1323               // If the host is in the lookupTable, it means that another
 1324               // thread is trying to look up the addresses of this host.
 1325               // This thread should wait.
 1326               while (lookupTable.containsKey(host)) {
 1327                   try {
 1328                       lookupTable.wait();
 1329                   } catch (InterruptedException e) {
 1330                   }
 1331               }
 1332           }
 1333   
 1334           // The other thread has finished looking up the addresses of
 1335           // the host. This thread should retry to get the addresses
 1336           // from the addressCache. If it doesn't get the addresses from
 1337           // the cache, it will try to look up the addresses itself.
 1338           InetAddress[] addresses = getCachedAddresses(host);
 1339           if (addresses == null) {
 1340               synchronized (lookupTable) {
 1341                   lookupTable.put(host, null);
 1342                   return null;
 1343               }
 1344           }
 1345   
 1346           return addresses;
 1347       }
 1348   
 1349       private static void updateLookupTable(String host) {
 1350           synchronized (lookupTable) {
 1351               lookupTable.remove(host);
 1352               lookupTable.notifyAll();
 1353           }
 1354       }
 1355   
 1356       /**
 1357        * Returns an <code>InetAddress</code> object given the raw IP address .
 1358        * The argument is in network byte order: the highest order
 1359        * byte of the address is in <code>getAddress()[0]</code>.
 1360        *
 1361        * <p> This method doesn't block, i.e. no reverse name service lookup
 1362        * is performed.
 1363        *
 1364        * <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
 1365        * must be 16 bytes long
 1366        *
 1367        * @param addr the raw IP address in network byte order
 1368        * @return  an InetAddress object created from the raw IP address.
 1369        * @exception  UnknownHostException  if IP address is of illegal length
 1370        * @since 1.4
 1371        */
 1372       public static InetAddress getByAddress(byte[] addr)
 1373           throws UnknownHostException {
 1374           return getByAddress(null, addr);
 1375       }
 1376   
 1377       private static InetAddress cachedLocalHost = null;
 1378       private static long cacheTime = 0;
 1379       private static final long maxCacheTime = 5000L;
 1380       private static final Object cacheLock = new Object();
 1381   
 1382       /**
 1383        * Returns the address of the local host. This is achieved by retrieving
 1384        * the name of the host from the system, then resolving that name into
 1385        * an <code>InetAddress</code>.
 1386        *
 1387        * <P>Note: The resolved address may be cached for a short period of time.
 1388        * </P>
 1389        *
 1390        * <p>If there is a security manager, its
 1391        * <code>checkConnect</code> method is called
 1392        * with the local host name and <code>-1</code>
 1393        * as its arguments to see if the operation is allowed.
 1394        * If the operation is not allowed, an InetAddress representing
 1395        * the loopback address is returned.
 1396        *
 1397        * @return     the address of the local host.
 1398        *
 1399        * @exception  UnknownHostException  if the local host name could not
 1400        *             be resolved into an address.
 1401        *
 1402        * @see SecurityManager#checkConnect
 1403        * @see java.net.InetAddress#getByName(java.lang.String)
 1404        */
 1405       public static InetAddress getLocalHost() throws UnknownHostException {
 1406   
 1407           SecurityManager security = System.getSecurityManager();
 1408           try {
 1409               String local = impl.getLocalHostName();
 1410   
 1411               if (security != null) {
 1412                   security.checkConnect(local, -1);
 1413               }
 1414   
 1415               if (local.equals("localhost")) {
 1416                   return impl.loopbackAddress();
 1417               }
 1418   
 1419               InetAddress ret = null;
 1420               synchronized (cacheLock) {
 1421                   long now = System.currentTimeMillis();
 1422                   if (cachedLocalHost != null) {
 1423                       if ((now - cacheTime) < maxCacheTime) // Less than 5s old?
 1424                           ret = cachedLocalHost;
 1425                       else
 1426                           cachedLocalHost = null;
 1427                   }
 1428   
 1429                   // we are calling getAddressesFromNameService directly
 1430                   // to avoid getting localHost from cache
 1431                   if (ret == null) {
 1432                       InetAddress[] localAddrs;
 1433                       try {
 1434                           localAddrs =
 1435                               InetAddress.getAddressesFromNameService(local, null);
 1436                       } catch (UnknownHostException uhe) {
 1437                           // Rethrow with a more informative error message.
 1438                           UnknownHostException uhe2 =
 1439                               new UnknownHostException(local + ": " +
 1440                                                        uhe.getMessage());
 1441                           uhe2.initCause(uhe);
 1442                           throw uhe2;
 1443                       }
 1444                       cachedLocalHost = localAddrs[0];
 1445                       cacheTime = now;
 1446                       ret = localAddrs[0];
 1447                   }
 1448               }
 1449               return ret;
 1450           } catch (java.lang.SecurityException e) {
 1451               return impl.loopbackAddress();
 1452           }
 1453       }
 1454   
 1455       /**
 1456        * Perform class load-time initializations.
 1457        */
 1458       private static native void init();
 1459   
 1460   
 1461       /*
 1462        * Returns the InetAddress representing anyLocalAddress
 1463        * (typically 0.0.0.0 or ::0)
 1464        */
 1465       static InetAddress anyLocalAddress() {
 1466           return impl.anyLocalAddress();
 1467       }
 1468   
 1469       /*
 1470        * Load and instantiate an underlying impl class
 1471        */
 1472       static InetAddressImpl loadImpl(String implName) {
 1473           Object impl = null;
 1474   
 1475           /*
 1476            * Property "impl.prefix" will be prepended to the classname
 1477            * of the implementation object we instantiate, to which we
 1478            * delegate the real work (like native methods).  This
 1479            * property can vary across implementations of the java.
 1480            * classes.  The default is an empty String "".
 1481            */
 1482           String prefix = AccessController.doPrivileged(
 1483                         new GetPropertyAction("impl.prefix", ""));
 1484           try {
 1485               impl = Class.forName("java.net." + prefix + implName).newInstance();
 1486           } catch (ClassNotFoundException e) {
 1487               System.err.println("Class not found: java.net." + prefix +
 1488                                  implName + ":\ncheck impl.prefix property " +
 1489                                  "in your properties file.");
 1490           } catch (InstantiationException e) {
 1491               System.err.println("Could not instantiate: java.net." + prefix +
 1492                                  implName + ":\ncheck impl.prefix property " +
 1493                                  "in your properties file.");
 1494           } catch (IllegalAccessException e) {
 1495               System.err.println("Cannot access class: java.net." + prefix +
 1496                                  implName + ":\ncheck impl.prefix property " +
 1497                                  "in your properties file.");
 1498           }
 1499   
 1500           if (impl == null) {
 1501               try {
 1502                   impl = Class.forName(implName).newInstance();
 1503               } catch (Exception e) {
 1504                   throw new Error("System property impl.prefix incorrect");
 1505               }
 1506           }
 1507   
 1508           return (InetAddressImpl) impl;
 1509       }
 1510   
 1511       private void readObjectNoData (ObjectInputStream s) throws
 1512                            IOException, ClassNotFoundException {
 1513           if (getClass().getClassLoader() != null) {
 1514               throw new SecurityException ("invalid address type");
 1515           }
 1516       }
 1517   
 1518       private void readObject (ObjectInputStream s) throws
 1519                            IOException, ClassNotFoundException {
 1520           s.defaultReadObject ();
 1521           if (getClass().getClassLoader() != null) {
 1522               hostName = null;
 1523               address = 0;
 1524               throw new SecurityException ("invalid address type");
 1525           }
 1526       }
 1527   }
 1528   
 1529   /*
 1530    * Simple factory to create the impl
 1531    */
 1532   class InetAddressImplFactory {
 1533   
 1534       static InetAddressImpl create() {
 1535           return InetAddress.loadImpl(isIPv6Supported() ?
 1536                                       "Inet6AddressImpl" : "Inet4AddressImpl");
 1537       }
 1538   
 1539       static native boolean isIPv6Supported();
 1540   }

Home » openjdk-7 » java » net » [javadoc | source]