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