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

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