History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/net/InetAddress.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/net/InetAddress.java+1540−0
@@ -0,0 +1,1540 @@
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+}