0001: /*
0002: * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025:
0026: package java.net;
0027:
0028: import java.util.HashMap;
0029: import java.util.LinkedHashMap;
0030: import java.util.Random;
0031: import java.util.Iterator;
0032: import java.util.LinkedList;
0033: import java.util.List;
0034: import java.util.ArrayList;
0035: import java.security.AccessController;
0036: import java.io.ObjectStreamException;
0037: import java.io.IOException;
0038: import sun.security.action.*;
0039: import sun.net.InetAddressCachePolicy;
0040: import sun.net.util.IPAddressUtil;
0041: import sun.misc.Service;
0042: import sun.net.spi.nameservice.*;
0043:
0044: /**
0045: * This class represents an Internet Protocol (IP) address.
0046: *
0047: * <p> An IP address is either a 32-bit or 128-bit unsigned number
0048: * used by IP, a lower-level protocol on which protocols like UDP and
0049: * TCP are built. The IP address architecture is defined by <a
0050: * href="http://www.ietf.org/rfc/rfc790.txt"><i>RFC 790:
0051: * Assigned Numbers</i></a>, <a
0052: * href="http://www.ietf.org/rfc/rfc1918.txt"> <i>RFC 1918:
0053: * Address Allocation for Private Internets</i></a>, <a
0054: * href="http://www.ietf.org/rfc/rfc2365.txt"><i>RFC 2365:
0055: * Administratively Scoped IP Multicast</i></a>, and <a
0056: * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC 2373: IP
0057: * Version 6 Addressing Architecture</i></a>. An instance of an
0058: * InetAddress consists of an IP address and possibly its
0059: * corresponding host name (depending on whether it is constructed
0060: * with a host name or whether it has already done reverse host name
0061: * resolution).
0062: *
0063: * <h4> Address types </h4>
0064: *
0065: * <blockquote><table cellspacing=2 summary="Description of unicast and multicast address types">
0066: * <tr><th valign=top><i>unicast</i></th>
0067: * <td>An identifier for a single interface. A packet sent to
0068: * a unicast address is delivered to the interface identified by
0069: * that address.
0070: *
0071: * <p> The Unspecified Address -- Also called anylocal or wildcard
0072: * address. It must never be assigned to any node. It indicates the
0073: * absence of an address. One example of its use is as the target of
0074: * bind, which allows a server to accept a client connection on any
0075: * interface, in case the server host has multiple interfaces.
0076: *
0077: * <p> The <i>unspecified</i> address must not be used as
0078: * the destination address of an IP packet.
0079: *
0080: * <p> The <i>Loopback</i> Addresses -- This is the address
0081: * assigned to the loopback interface. Anything sent to this
0082: * IP address loops around and becomes IP input on the local
0083: * host. This address is often used when testing a
0084: * client.</td></tr>
0085: * <tr><th valign=top><i>multicast</i></th>
0086: * <td>An identifier for a set of interfaces (typically belonging
0087: * to different nodes). A packet sent to a multicast address is
0088: * delivered to all interfaces identified by that address.</td></tr>
0089: * </table></blockquote>
0090: *
0091: * <h4> IP address scope </h4>
0092: *
0093: * <p> <i>Link-local</i> addresses are designed to be used for addressing
0094: * on a single link for purposes such as auto-address configuration,
0095: * neighbor discovery, or when no routers are present.
0096: *
0097: * <p> <i>Site-local</i> addresses are designed to be used for addressing
0098: * inside of a site without the need for a global prefix.
0099: *
0100: * <p> <i>Global</i> addresses are unique across the internet.
0101: *
0102: * <h4> Textual representation of IP addresses </h4>
0103: *
0104: * The textual representation of an IP address is address family specific.
0105: *
0106: * <p>
0107: *
0108: * For IPv4 address format, please refer to <A
0109: * HREF="Inet4Address.html#format">Inet4Address#format</A>; For IPv6
0110: * address format, please refer to <A
0111: * HREF="Inet6Address.html#format">Inet6Address#format</A>.
0112: *
0113: * <h4> Host Name Resolution </h4>
0114: *
0115: * Host name-to-IP address <i>resolution</i> is accomplished through
0116: * the use of a combination of local machine configuration information
0117: * and network naming services such as the Domain Name System (DNS)
0118: * and Network Information Service(NIS). The particular naming
0119: * services(s) being used is by default the local machine configured
0120: * one. For any host name, its corresponding IP address is returned.
0121: *
0122: * <p> <i>Reverse name resolution</i> means that for any IP address,
0123: * the host associated with the IP address is returned.
0124: *
0125: * <p> The InetAddress class provides methods to resolve host names to
0126: * their IP addresses and vice versa.
0127: *
0128: * <h4> InetAddress Caching </h4>
0129: *
0130: * The InetAddress class has a cache to store successful as well as
0131: * unsuccessful host name resolutions.
0132: *
0133: * <p> By default, when a security manager is installed, in order to
0134: * protect against DNS spoofing attacks,
0135: * the result of positive host name resolutions are
0136: * cached forever. When a security manager is not installed, the default
0137: * behavior is to cache entries for a finite (implementation dependent)
0138: * period of time. The result of unsuccessful host
0139: * name resolution is cached for a very short period of time (10
0140: * seconds) to improve performance.
0141: *
0142: * <p> If the default behavior is not desired, then a Java security property
0143: * can be set to a different Time-to-live (TTL) value for positive
0144: * caching. Likewise, a system admin can configure a different
0145: * negative caching TTL value when needed.
0146: *
0147: * <p> Two Java security properties control the TTL values used for
0148: * positive and negative host name resolution caching:
0149: *
0150: * <blockquote>
0151: * <dl>
0152: * <dt><b>networkaddress.cache.ttl</b></dt>
0153: * <dd>Indicates the caching policy for successful name lookups from
0154: * the name service. The value is specified as as integer to indicate
0155: * the number of seconds to cache the successful lookup. The default
0156: * setting is to cache for an implementation specific period of time.
0157: * <p>
0158: * A value of -1 indicates "cache forever".
0159: * </dd>
0160: * <p>
0161: * <dt><b>networkaddress.cache.negative.ttl</b> (default: 10)</dt>
0162: * <dd>Indicates the caching policy for un-successful name lookups
0163: * from the name service. The value is specified as as integer to
0164: * indicate the number of seconds to cache the failure for
0165: * un-successful lookups.
0166: * <p>
0167: * A value of 0 indicates "never cache".
0168: * A value of -1 indicates "cache forever".
0169: * </dd>
0170: * </dl>
0171: * </blockquote>
0172: *
0173: * @author Chris Warth
0174: * @version 1.125, 06/12/07
0175: * @see java.net.InetAddress#getByAddress(byte[])
0176: * @see java.net.InetAddress#getByAddress(java.lang.String, byte[])
0177: * @see java.net.InetAddress#getAllByName(java.lang.String)
0178: * @see java.net.InetAddress#getByName(java.lang.String)
0179: * @see java.net.InetAddress#getLocalHost()
0180: * @since JDK1.0
0181: */
0182: public class InetAddress implements java.io.Serializable {
0183: /**
0184: * Specify the address family: Internet Protocol, Version 4
0185: * @since 1.4
0186: */
0187: static final int IPv4 = 1;
0188:
0189: /**
0190: * Specify the address family: Internet Protocol, Version 6
0191: * @since 1.4
0192: */
0193: static final int IPv6 = 2;
0194:
0195: /* Specify address family preference */
0196: static transient boolean preferIPv6Address = false;
0197:
0198: /**
0199: * @serial
0200: */
0201: String hostName;
0202:
0203: /**
0204: * Holds a 32-bit IPv4 address.
0205: *
0206: * @serial
0207: */
0208: int address;
0209:
0210: /**
0211: * Specifies the address family type, for instance, '1' for IPv4
0212: * addresses, and '2' for IPv6 addresses.
0213: *
0214: * @serial
0215: */
0216: int family;
0217:
0218: /* Used to store the name service provider */
0219: private static List<NameService> nameServices = null;
0220:
0221: /* Used to store the best available hostname */
0222: private transient String canonicalHostName = null;
0223:
0224: /** use serialVersionUID from JDK 1.0.2 for interoperability */
0225: private static final long serialVersionUID = 3286316764910316507L;
0226:
0227: /*
0228: * Load net library into runtime, and perform initializations.
0229: */
0230: static {
0231: preferIPv6Address = ((Boolean) java.security.AccessController
0232: .doPrivileged(new GetBooleanAction(
0233: "java.net.preferIPv6Addresses")))
0234: .booleanValue();
0235: AccessController.doPrivileged(new LoadLibraryAction("net"));
0236: init();
0237: }
0238:
0239: /**
0240: * Constructor for the Socket.accept() method.
0241: * This creates an empty InetAddress, which is filled in by
0242: * the accept() method. This InetAddress, however, is not
0243: * put in the address cache, since it is not created by name.
0244: */
0245: InetAddress() {
0246: }
0247:
0248: /**
0249: * Replaces the de-serialized object with an Inet4Address object.
0250: *
0251: * @return the alternate object to the de-serialized object.
0252: *
0253: * @throws ObjectStreamException if a new object replacing this
0254: * object could not be created
0255: */
0256: private Object readResolve() throws ObjectStreamException {
0257: // will replace the deserialized 'this' object
0258: return new Inet4Address(this .hostName, this .address);
0259: }
0260:
0261: /**
0262: * Utility routine to check if the InetAddress is an
0263: * IP multicast address.
0264: * @return a <code>boolean</code> indicating if the InetAddress is
0265: * an IP multicast address
0266: * @since JDK1.1
0267: */
0268: public boolean isMulticastAddress() {
0269: return false;
0270: }
0271:
0272: /**
0273: * Utility routine to check if the InetAddress in a wildcard address.
0274: * @return a <code>boolean</code> indicating if the Inetaddress is
0275: * a wildcard address.
0276: * @since 1.4
0277: */
0278: public boolean isAnyLocalAddress() {
0279: return false;
0280: }
0281:
0282: /**
0283: * Utility routine to check if the InetAddress is a loopback address.
0284: *
0285: * @return a <code>boolean</code> indicating if the InetAddress is
0286: * a loopback address; or false otherwise.
0287: * @since 1.4
0288: */
0289: public boolean isLoopbackAddress() {
0290: return false;
0291: }
0292:
0293: /**
0294: * Utility routine to check if the InetAddress is an link local address.
0295: *
0296: * @return a <code>boolean</code> indicating if the InetAddress is
0297: * a link local address; or false if address is not a link local unicast address.
0298: * @since 1.4
0299: */
0300: public boolean isLinkLocalAddress() {
0301: return false;
0302: }
0303:
0304: /**
0305: * Utility routine to check if the InetAddress is a site local address.
0306: *
0307: * @return a <code>boolean</code> indicating if the InetAddress is
0308: * a site local address; or false if address is not a site local unicast address.
0309: * @since 1.4
0310: */
0311: public boolean isSiteLocalAddress() {
0312: return false;
0313: }
0314:
0315: /**
0316: * Utility routine to check if the multicast address has global scope.
0317: *
0318: * @return a <code>boolean</code> indicating if the address has
0319: * is a multicast address of global scope, false if it is not
0320: * of global scope or it is not a multicast address
0321: * @since 1.4
0322: */
0323: public boolean isMCGlobal() {
0324: return false;
0325: }
0326:
0327: /**
0328: * Utility routine to check if the multicast address has node scope.
0329: *
0330: * @return a <code>boolean</code> indicating if the address has
0331: * is a multicast address of node-local scope, false if it is not
0332: * of node-local scope or it is not a multicast address
0333: * @since 1.4
0334: */
0335: public boolean isMCNodeLocal() {
0336: return false;
0337: }
0338:
0339: /**
0340: * Utility routine to check if the multicast address has link scope.
0341: *
0342: * @return a <code>boolean</code> indicating if the address has
0343: * is a multicast address of link-local scope, false if it is not
0344: * of link-local scope or it is not a multicast address
0345: * @since 1.4
0346: */
0347: public boolean isMCLinkLocal() {
0348: return false;
0349: }
0350:
0351: /**
0352: * Utility routine to check if the multicast address has site scope.
0353: *
0354: * @return a <code>boolean</code> indicating if the address has
0355: * is a multicast address of site-local scope, false if it is not
0356: * of site-local scope or it is not a multicast address
0357: * @since 1.4
0358: */
0359: public boolean isMCSiteLocal() {
0360: return false;
0361: }
0362:
0363: /**
0364: * Utility routine to check if the multicast address has organization scope.
0365: *
0366: * @return a <code>boolean</code> indicating if the address has
0367: * is a multicast address of organization-local scope,
0368: * false if it is not of organization-local scope
0369: * or it is not a multicast address
0370: * @since 1.4
0371: */
0372: public boolean isMCOrgLocal() {
0373: return false;
0374: }
0375:
0376: /**
0377: * Test whether that address is reachable. Best effort is made by the
0378: * implementation to try to reach the host, but firewalls and server
0379: * configuration may block requests resulting in a unreachable status
0380: * while some specific ports may be accessible.
0381: * A typical implementation will use ICMP ECHO REQUESTs if the
0382: * privilege can be obtained, otherwise it will try to establish
0383: * a TCP connection on port 7 (Echo) of the destination host.
0384: * <p>
0385: * The timeout value, in milliseconds, indicates the maximum amount of time
0386: * the try should take. If the operation times out before getting an
0387: * answer, the host is deemed unreachable. A negative value will result
0388: * in an IllegalArgumentException being thrown.
0389: *
0390: * @param timeout the time, in milliseconds, before the call aborts
0391: * @return a <code>boolean</code> indicating if the address is reachable.
0392: * @throws IOException if a network error occurs
0393: * @throws IllegalArgumentException if <code>timeout</code> is negative.
0394: * @since 1.5
0395: */
0396: public boolean isReachable(int timeout) throws IOException {
0397: return isReachable(null, 0, timeout);
0398: }
0399:
0400: /**
0401: * Test whether that address is reachable. Best effort is made by the
0402: * implementation to try to reach the host, but firewalls and server
0403: * configuration may block requests resulting in a unreachable status
0404: * while some specific ports may be accessible.
0405: * A typical implementation will use ICMP ECHO REQUESTs if the
0406: * privilege can be obtained, otherwise it will try to establish
0407: * a TCP connection on port 7 (Echo) of the destination host.
0408: * <p>
0409: * The <code>network interface</code> and <code>ttl</code> parameters
0410: * let the caller specify which network interface the test will go through
0411: * and the maximum number of hops the packets should go through.
0412: * A negative value for the <code>ttl</code> will result in an
0413: * IllegalArgumentException being thrown.
0414: * <p>
0415: * The timeout value, in milliseconds, indicates the maximum amount of time
0416: * the try should take. If the operation times out before getting an
0417: * answer, the host is deemed unreachable. A negative value will result
0418: * in an IllegalArgumentException being thrown.
0419: *
0420: * @param netif the NetworkInterface through which the
0421: * test will be done, or null for any interface
0422: * @param ttl the maximum numbers of hops to try or 0 for the
0423: * default
0424: * @param timeout the time, in milliseconds, before the call aborts
0425: * @throws IllegalArgumentException if either <code>timeout</code>
0426: * or <code>ttl</code> are negative.
0427: * @return a <code>boolean</code>indicating if the address is reachable.
0428: * @throws IOException if a network error occurs
0429: * @since 1.5
0430: */
0431: public boolean isReachable(NetworkInterface netif, int ttl,
0432: int timeout) throws IOException {
0433: if (ttl < 0)
0434: throw new IllegalArgumentException("ttl can't be negative");
0435: if (timeout < 0)
0436: throw new IllegalArgumentException(
0437: "timeout can't be negative");
0438:
0439: return impl.isReachable(this , timeout, netif, ttl);
0440: }
0441:
0442: /**
0443: * Gets the host name for this IP address.
0444: *
0445: * <p>If this InetAddress was created with a host name,
0446: * this host name will be remembered and returned;
0447: * otherwise, a reverse name lookup will be performed
0448: * and the result will be returned based on the system
0449: * configured name lookup service. If a lookup of the name service
0450: * is required, call
0451: * {@link #getCanonicalHostName() getCanonicalHostName}.
0452: *
0453: * <p>If there is a security manager, its
0454: * <code>checkConnect</code> method is first called
0455: * with the hostname and <code>-1</code>
0456: * as its arguments to see if the operation is allowed.
0457: * If the operation is not allowed, it will return
0458: * the textual representation of the IP address.
0459: *
0460: * @return the host name for this IP address, or if the operation
0461: * is not allowed by the security check, the textual
0462: * representation of the IP address.
0463: *
0464: * @see InetAddress#getCanonicalHostName
0465: * @see SecurityManager#checkConnect
0466: */
0467: public String getHostName() {
0468: return getHostName(true);
0469: }
0470:
0471: /**
0472: * Returns the hostname for this address.
0473: * If the host is equal to null, then this address refers to any
0474: * of the local machine's available network addresses.
0475: * this is package private so SocketPermission can make calls into
0476: * here without a security check.
0477: *
0478: * <p>If there is a security manager, this method first
0479: * calls its <code>checkConnect</code> method
0480: * with the hostname and <code>-1</code>
0481: * as its arguments to see if the calling code is allowed to know
0482: * the hostname for this IP address, i.e., to connect to the host.
0483: * If the operation is not allowed, it will return
0484: * the textual representation of the IP address.
0485: *
0486: * @return the host name for this IP address, or if the operation
0487: * is not allowed by the security check, the textual
0488: * representation of the IP address.
0489: *
0490: * @param check make security check if true
0491: *
0492: * @see SecurityManager#checkConnect
0493: */
0494: String getHostName(boolean check) {
0495: if (hostName == null) {
0496: hostName = InetAddress.getHostFromNameService(this , check);
0497: }
0498: return hostName;
0499: }
0500:
0501: /**
0502: * Gets the fully qualified domain name for this IP address.
0503: * Best effort method, meaning we may not be able to return
0504: * the FQDN depending on the underlying system configuration.
0505: *
0506: * <p>If there is a security manager, this method first
0507: * calls its <code>checkConnect</code> method
0508: * with the hostname and <code>-1</code>
0509: * as its arguments to see if the calling code is allowed to know
0510: * the hostname for this IP address, i.e., to connect to the host.
0511: * If the operation is not allowed, it will return
0512: * the textual representation of the IP address.
0513: *
0514: * @return the fully qualified domain name for this IP address,
0515: * or if the operation is not allowed by the security check,
0516: * the textual representation of the IP address.
0517: *
0518: * @see SecurityManager#checkConnect
0519: *
0520: * @since 1.4
0521: */
0522: public String getCanonicalHostName() {
0523: if (canonicalHostName == null) {
0524: canonicalHostName = InetAddress.getHostFromNameService(
0525: this , true);
0526: }
0527: return canonicalHostName;
0528: }
0529:
0530: /**
0531: * Returns the hostname for this address.
0532: *
0533: * <p>If there is a security manager, this method first
0534: * calls its <code>checkConnect</code> method
0535: * with the hostname and <code>-1</code>
0536: * as its arguments to see if the calling code is allowed to know
0537: * the hostname for this IP address, i.e., to connect to the host.
0538: * If the operation is not allowed, it will return
0539: * the textual representation of the IP address.
0540: *
0541: * @return the host name for this IP address, or if the operation
0542: * is not allowed by the security check, the textual
0543: * representation of the IP address.
0544: *
0545: * @param check make security check if true
0546: *
0547: * @see SecurityManager#checkConnect
0548: */
0549: private static String getHostFromNameService(InetAddress addr,
0550: boolean check) {
0551: String host = null;
0552: for (NameService nameService : nameServices) {
0553: try {
0554: // first lookup the hostname
0555: host = nameService.getHostByAddr(addr.getAddress());
0556:
0557: /* check to see if calling code is allowed to know
0558: * the hostname for this IP address, ie, connect to the host
0559: */
0560: if (check) {
0561: SecurityManager sec = System.getSecurityManager();
0562: if (sec != null) {
0563: sec.checkConnect(host, -1);
0564: }
0565: }
0566:
0567: /* now get all the IP addresses for this hostname,
0568: * and make sure one of them matches the original IP
0569: * address. We do this to try and prevent spoofing.
0570: */
0571:
0572: InetAddress[] arr = InetAddress.getAllByName0(host,
0573: check);
0574: boolean ok = false;
0575:
0576: if (arr != null) {
0577: for (int i = 0; !ok && i < arr.length; i++) {
0578: ok = addr.equals(arr[i]);
0579: }
0580: }
0581:
0582: //XXX: if it looks a spoof just return the address?
0583: if (!ok) {
0584: host = addr.getHostAddress();
0585: return host;
0586: }
0587:
0588: break;
0589:
0590: } catch (SecurityException e) {
0591: host = addr.getHostAddress();
0592: break;
0593: } catch (UnknownHostException e) {
0594: host = addr.getHostAddress();
0595: // let next provider resolve the hostname
0596: }
0597: }
0598:
0599: return host;
0600: }
0601:
0602: /**
0603: * Returns the raw IP address of this <code>InetAddress</code>
0604: * object. The result is in network byte order: the highest order
0605: * byte of the address is in <code>getAddress()[0]</code>.
0606: *
0607: * @return the raw IP address of this object.
0608: */
0609: public byte[] getAddress() {
0610: return null;
0611: }
0612:
0613: /**
0614: * Returns the IP address string in textual presentation.
0615: *
0616: * @return the raw IP address in a string format.
0617: * @since JDK1.0.2
0618: */
0619: public String getHostAddress() {
0620: return null;
0621: }
0622:
0623: /**
0624: * Returns a hashcode for this IP address.
0625: *
0626: * @return a hash code value for this IP address.
0627: */
0628: public int hashCode() {
0629: return -1;
0630: }
0631:
0632: /**
0633: * Compares this object against the specified object.
0634: * The result is <code>true</code> if and only if the argument is
0635: * not <code>null</code> and it represents the same IP address as
0636: * this object.
0637: * <p>
0638: * Two instances of <code>InetAddress</code> represent the same IP
0639: * address if the length of the byte arrays returned by
0640: * <code>getAddress</code> is the same for both, and each of the
0641: * array components is the same for the byte arrays.
0642: *
0643: * @param obj the object to compare against.
0644: * @return <code>true</code> if the objects are the same;
0645: * <code>false</code> otherwise.
0646: * @see java.net.InetAddress#getAddress()
0647: */
0648: public boolean equals(Object obj) {
0649: return false;
0650: }
0651:
0652: /**
0653: * Converts this IP address to a <code>String</code>. The
0654: * string returned is of the form: hostname / literal IP
0655: * address.
0656: *
0657: * If the host name is unresolved, no reverse name service lookup
0658: * is performed. The hostname part will be represented by an empty string.
0659: *
0660: * @return a string representation of this IP address.
0661: */
0662: public String toString() {
0663: return ((hostName != null) ? hostName : "") + "/"
0664: + getHostAddress();
0665: }
0666:
0667: /*
0668: * Cached addresses - our own litle nis, not!
0669: */
0670: private static Cache addressCache = new Cache(Cache.Type.Positive);
0671:
0672: private static Cache negativeCache = new Cache(Cache.Type.Negative);
0673:
0674: private static boolean addressCacheInit = false;
0675:
0676: static InetAddress[] unknown_array; // put THIS in cache
0677:
0678: static InetAddressImpl impl;
0679:
0680: private static HashMap lookupTable = new HashMap();
0681:
0682: /**
0683: * Represents a cache entry
0684: */
0685: static final class CacheEntry {
0686:
0687: CacheEntry(Object address, long expiration) {
0688: this .address = address;
0689: this .expiration = expiration;
0690: }
0691:
0692: Object address;
0693: long expiration;
0694: }
0695:
0696: /**
0697: * A cache that manages entries based on a policy specified
0698: * at creation time.
0699: */
0700: static final class Cache {
0701: private LinkedHashMap cache;
0702: private Type type;
0703:
0704: enum Type {
0705: Positive, Negative
0706: };
0707:
0708: /**
0709: * Create cache
0710: */
0711: public Cache(Type type) {
0712: this .type = type;
0713: cache = new LinkedHashMap();
0714: }
0715:
0716: private int getPolicy() {
0717: if (type == Type.Positive) {
0718: return InetAddressCachePolicy.get();
0719: } else {
0720: return InetAddressCachePolicy.getNegative();
0721: }
0722: }
0723:
0724: /**
0725: * Add an entry to the cache. If there's already an
0726: * entry then for this host then the entry will be
0727: * replaced.
0728: */
0729: public Cache put(String host, Object address) {
0730: int policy = getPolicy();
0731: if (policy == InetAddressCachePolicy.NEVER) {
0732: return this ;
0733: }
0734:
0735: // purge any expired entries
0736:
0737: if (policy != InetAddressCachePolicy.FOREVER) {
0738:
0739: // As we iterate in insertion order we can
0740: // terminate when a non-expired entry is found.
0741: LinkedList expired = new LinkedList();
0742: Iterator i = cache.keySet().iterator();
0743: long now = System.currentTimeMillis();
0744: while (i.hasNext()) {
0745: String key = (String) i.next();
0746: CacheEntry entry = (CacheEntry) cache.get(key);
0747:
0748: if (entry.expiration >= 0 && entry.expiration < now) {
0749: expired.add(key);
0750: } else {
0751: break;
0752: }
0753: }
0754:
0755: i = expired.iterator();
0756: while (i.hasNext()) {
0757: cache.remove(i.next());
0758: }
0759: }
0760:
0761: // create new entry and add it to the cache
0762: // -- as a HashMap replaces existing entries we
0763: // don't need to explicitly check if there is
0764: // already an entry for this host.
0765: long expiration;
0766: if (policy == InetAddressCachePolicy.FOREVER) {
0767: expiration = -1;
0768: } else {
0769: expiration = System.currentTimeMillis()
0770: + (policy * 1000);
0771: }
0772: CacheEntry entry = new CacheEntry(address, expiration);
0773: cache.put(host, entry);
0774: return this ;
0775: }
0776:
0777: /**
0778: * Query the cache for the specific host. If found then
0779: * return its CacheEntry, or null if not found.
0780: */
0781: public CacheEntry get(String host) {
0782: int policy = getPolicy();
0783: if (policy == InetAddressCachePolicy.NEVER) {
0784: return null;
0785: }
0786: CacheEntry entry = (CacheEntry) cache.get(host);
0787:
0788: // check if entry has expired
0789: if (entry != null
0790: && policy != InetAddressCachePolicy.FOREVER) {
0791: if (entry.expiration >= 0
0792: && entry.expiration < System
0793: .currentTimeMillis()) {
0794: cache.remove(host);
0795: entry = null;
0796: }
0797: }
0798:
0799: return entry;
0800: }
0801: }
0802:
0803: /*
0804: * Initialize cache and insert anyLocalAddress into the
0805: * unknown array with no expiry.
0806: */
0807: private static void cacheInitIfNeeded() {
0808: assert Thread.holdsLock(addressCache);
0809: if (addressCacheInit) {
0810: return;
0811: }
0812: unknown_array = new InetAddress[1];
0813: unknown_array[0] = impl.anyLocalAddress();
0814:
0815: addressCache.put(impl.anyLocalAddress().getHostName(),
0816: unknown_array);
0817:
0818: addressCacheInit = true;
0819: }
0820:
0821: /*
0822: * Cache the given hostname and address.
0823: */
0824: private static void cacheAddress(String hostname, Object address,
0825: boolean success) {
0826: hostname = hostname.toLowerCase();
0827: synchronized (addressCache) {
0828: cacheInitIfNeeded();
0829: if (success) {
0830: addressCache.put(hostname, address);
0831: } else {
0832: negativeCache.put(hostname, address);
0833: }
0834: }
0835: }
0836:
0837: /*
0838: * Lookup hostname in cache (positive & negative cache). If
0839: * found return address, null if not found.
0840: */
0841: private static Object getCachedAddress(String hostname) {
0842: hostname = hostname.toLowerCase();
0843:
0844: // search both positive & negative caches
0845:
0846: synchronized (addressCache) {
0847: CacheEntry entry;
0848:
0849: cacheInitIfNeeded();
0850:
0851: entry = (CacheEntry) addressCache.get(hostname);
0852: if (entry == null) {
0853: entry = (CacheEntry) negativeCache.get(hostname);
0854: }
0855:
0856: if (entry != null) {
0857: return entry.address;
0858: }
0859: }
0860:
0861: // not found
0862: return null;
0863: }
0864:
0865: private static NameService createNSProvider(String provider) {
0866: if (provider == null)
0867: return null;
0868:
0869: NameService nameService = null;
0870: if (provider.equals("default")) {
0871: // initialize the default name service
0872: nameService = new NameService() {
0873: public InetAddress[] lookupAllHostAddr(String host)
0874: throws UnknownHostException {
0875: return impl.lookupAllHostAddr(host);
0876: }
0877:
0878: public String getHostByAddr(byte[] addr)
0879: throws UnknownHostException {
0880: return impl.getHostByAddr(addr);
0881: }
0882: };
0883: } else {
0884: final String providerName = provider;
0885: try {
0886: nameService = java.security.AccessController
0887: .doPrivileged(new java.security.PrivilegedExceptionAction<NameService>() {
0888: public NameService run() {
0889: Iterator itr = Service
0890: .providers(NameServiceDescriptor.class);
0891: while (itr.hasNext()) {
0892: NameServiceDescriptor nsd = (NameServiceDescriptor) itr
0893: .next();
0894: if (providerName
0895: .equalsIgnoreCase(nsd
0896: .getType()
0897: + ","
0898: + nsd
0899: .getProviderName())) {
0900: try {
0901: return nsd
0902: .createNameService();
0903: } catch (Exception e) {
0904: e.printStackTrace();
0905: System.err
0906: .println("Cannot create name service:"
0907: + providerName
0908: + ": " + e);
0909: }
0910: }
0911: }
0912:
0913: return null;
0914: }
0915: });
0916: } catch (java.security.PrivilegedActionException e) {
0917: }
0918: }
0919:
0920: return nameService;
0921: }
0922:
0923: static {
0924: // create the impl
0925: impl = (new InetAddressImplFactory()).create();
0926:
0927: // get name service if provided and requested
0928: String provider = null;
0929: ;
0930: String propPrefix = "sun.net.spi.nameservice.provider.";
0931: int n = 1;
0932: nameServices = new ArrayList<NameService>();
0933: provider = (String) AccessController
0934: .doPrivileged(new GetPropertyAction(propPrefix + n));
0935: while (provider != null) {
0936: NameService ns = createNSProvider(provider);
0937: if (ns != null)
0938: nameServices.add(ns);
0939:
0940: n++;
0941: provider = (String) AccessController
0942: .doPrivileged(new GetPropertyAction(propPrefix + n));
0943: }
0944:
0945: // if not designate any name services provider,
0946: // creat a default one
0947: if (nameServices.size() == 0) {
0948: NameService ns = createNSProvider("default");
0949: nameServices.add(ns);
0950: }
0951: }
0952:
0953: /**
0954: * Create an InetAddress based on the provided host name and IP address
0955: * No name service is checked for the validity of the address.
0956: *
0957: * <p> The host name can either be a machine name, such as
0958: * "<code>java.sun.com</code>", or a textual representation of its IP
0959: * address.
0960: * <p> No validity checking is done on the host name either.
0961: *
0962: * <p> If addr specifies an IPv4 address an instance of Inet4Address
0963: * will be returned; otherwise, an instance of Inet6Address
0964: * will be returned.
0965: *
0966: * <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
0967: * must be 16 bytes long
0968: *
0969: * @param host the specified host
0970: * @param addr the raw IP address in network byte order
0971: * @return an InetAddress object created from the raw IP address.
0972: * @exception UnknownHostException if IP address is of illegal length
0973: * @since 1.4
0974: */
0975: public static InetAddress getByAddress(String host, byte[] addr)
0976: throws UnknownHostException {
0977: if (host != null && host.length() > 0 && host.charAt(0) == '[') {
0978: if (host.charAt(host.length() - 1) == ']') {
0979: host = host.substring(1, host.length() - 1);
0980: }
0981: }
0982: if (addr != null) {
0983: if (addr.length == Inet4Address.INADDRSZ) {
0984: return new Inet4Address(host, addr);
0985: } else if (addr.length == Inet6Address.INADDRSZ) {
0986: byte[] newAddr = IPAddressUtil
0987: .convertFromIPv4MappedAddress(addr);
0988: if (newAddr != null) {
0989: return new Inet4Address(host, newAddr);
0990: } else {
0991: return new Inet6Address(host, addr);
0992: }
0993: }
0994: }
0995: throw new UnknownHostException("addr is of illegal length");
0996: }
0997:
0998: /**
0999: * Determines the IP address of a host, given the host's name.
1000: *
1001: * <p> The host name can either be a machine name, such as
1002: * "<code>java.sun.com</code>", or a textual representation of its
1003: * IP address. If a literal IP address is supplied, only the
1004: * validity of the address format is checked.
1005: *
1006: * <p> For <code>host</code> specified in literal IPv6 address,
1007: * either the form defined in RFC 2732 or the literal IPv6 address
1008: * format defined in RFC 2373 is accepted. IPv6 scoped addresses are also
1009: * supported. See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6
1010: * scoped addresses.
1011: *
1012: * <p> If the host is <tt>null</tt> then an <tt>InetAddress</tt>
1013: * representing an address of the loopback interface is returned.
1014: * See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC 3330</a>
1015: * section 2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC 2373</a>
1016: * section 2.5.3. </p>
1017: *
1018: * @param host the specified host, or <code>null</code>.
1019: * @return an IP address for the given host name.
1020: * @exception UnknownHostException if no IP address for the
1021: * <code>host</code> could be found, or if a scope_id was specified
1022: * for a global IPv6 address.
1023: * @exception SecurityException if a security manager exists
1024: * and its checkConnect method doesn't allow the operation
1025: */
1026: public static InetAddress getByName(String host)
1027: throws UnknownHostException {
1028: return InetAddress.getAllByName(host)[0];
1029: }
1030:
1031: /**
1032: * Given the name of a host, returns an array of its IP addresses,
1033: * based on the configured name service on the system.
1034: *
1035: * <p> The host name can either be a machine name, such as
1036: * "<code>java.sun.com</code>", or a textual representation of its IP
1037: * address. If a literal IP address is supplied, only the
1038: * validity of the address format is checked.
1039: *
1040: * <p> For <code>host</code> specified in <i>literal IPv6 address</i>,
1041: * either the form defined in RFC 2732 or the literal IPv6 address
1042: * format defined in RFC 2373 is accepted. A literal IPv6 address may
1043: * also be qualified by appending a scoped zone identifier or scope_id.
1044: * The syntax and usage of scope_ids is described
1045: * <a href="Inet6Address.html#scoped">here</a>.
1046: * <p> If the host is <tt>null</tt> then an <tt>InetAddress</tt>
1047: * representing an address of the loopback interface is returned.
1048: * See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC 3330</a>
1049: * section 2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC 2373</a>
1050: * section 2.5.3. </p>
1051: *
1052: * <p> If there is a security manager and <code>host</code> is not
1053: * null and <code>host.length() </code> is not equal to zero, the
1054: * security manager's
1055: * <code>checkConnect</code> method is called
1056: * with the hostname and <code>-1</code>
1057: * as its arguments to see if the operation is allowed.
1058: *
1059: * @param host the name of the host, or <code>null</code>.
1060: * @return an array of all the IP addresses for a given host name.
1061: *
1062: * @exception UnknownHostException if no IP address for the
1063: * <code>host</code> could be found, or if a scope_id was specified
1064: * for a global IPv6 address.
1065: * @exception SecurityException if a security manager exists and its
1066: * <code>checkConnect</code> method doesn't allow the operation.
1067: *
1068: * @see SecurityManager#checkConnect
1069: */
1070: public static InetAddress[] getAllByName(String host)
1071: throws UnknownHostException {
1072:
1073: if (host == null || host.length() == 0) {
1074: InetAddress[] ret = new InetAddress[1];
1075: ret[0] = impl.loopbackAddress();
1076: return ret;
1077: }
1078:
1079: boolean ipv6Expected = false;
1080: if (host.charAt(0) == '[') {
1081: // This is supposed to be an IPv6 litteral
1082: if (host.length() > 2
1083: && host.charAt(host.length() - 1) == ']') {
1084: host = host.substring(1, host.length() - 1);
1085: ipv6Expected = true;
1086: } else {
1087: // This was supposed to be a IPv6 address, but it's not!
1088: throw new UnknownHostException(host);
1089: }
1090: }
1091:
1092: // if host is an IP address, we won't do further lookup
1093: if (Character.digit(host.charAt(0), 16) != -1
1094: || (host.charAt(0) == ':')) {
1095: byte[] addr = null;
1096: int numericZone = -1;
1097: String ifname = null;
1098: // see if it is IPv4 address
1099: addr = IPAddressUtil.textToNumericFormatV4(host);
1100: if (addr == null) {
1101: // see if it is IPv6 address
1102: // Check if a numeric or string zone id is present
1103: int pos;
1104: if ((pos = host.indexOf("%")) != -1) {
1105: numericZone = checkNumericZone(host);
1106: if (numericZone == -1) { /* remainder of string must be an ifname */
1107: ifname = host.substring(pos + 1);
1108: }
1109: }
1110: addr = IPAddressUtil.textToNumericFormatV6(host);
1111: } else if (ipv6Expected) {
1112: // Means an IPv4 litteral between brackets!
1113: throw new UnknownHostException("[" + host + "]");
1114: }
1115: InetAddress[] ret = new InetAddress[1];
1116: if (addr != null) {
1117: if (addr.length == Inet4Address.INADDRSZ) {
1118: ret[0] = new Inet4Address(null, addr);
1119: } else {
1120: if (ifname != null) {
1121: ret[0] = new Inet6Address(null, addr, ifname);
1122: } else {
1123: ret[0] = new Inet6Address(null, addr,
1124: numericZone);
1125: }
1126: }
1127: return ret;
1128: }
1129: } else if (ipv6Expected) {
1130: // We were expecting an IPv6 Litteral, but got something else
1131: throw new UnknownHostException("[" + host + "]");
1132: }
1133: return getAllByName0(host);
1134: }
1135:
1136: /**
1137: * Returns the loopback address.
1138: * <p>
1139: * The InetAddress returned will represent the IPv4
1140: * loopback address, 127.0.0.1, or the IPv6 loopback
1141: * address, ::1. The IPv4 loopback address returned
1142: * is only one of many in the form 127.*.*.*
1143: *
1144: * @return the InetAddress loopback instance.
1145: * @since 1.7
1146: */
1147: public static InetAddress getLoopbackAddress() {
1148: return impl.loopbackAddress();
1149: }
1150:
1151: /**
1152: * check if the literal address string has %nn appended
1153: * returns -1 if not, or the numeric value otherwise.
1154: *
1155: * %nn may also be a string that represents the displayName of
1156: * a currently available NetworkInterface.
1157: */
1158: private static int checkNumericZone(String s)
1159: throws UnknownHostException {
1160: int percent = s.indexOf('%');
1161: int slen = s.length();
1162: int digit, zone = 0;
1163: if (percent == -1) {
1164: return -1;
1165: }
1166: for (int i = percent + 1; i < slen; i++) {
1167: char c = s.charAt(i);
1168: if (c == ']') {
1169: if (i == percent + 1) {
1170: /* empty per-cent field */
1171: return -1;
1172: }
1173: break;
1174: }
1175: if ((digit = Character.digit(c, 10)) < 0) {
1176: return -1;
1177: }
1178: zone = (zone * 10) + digit;
1179: }
1180: return zone;
1181: }
1182:
1183: private static InetAddress[] getAllByName0(String host)
1184: throws UnknownHostException {
1185: return getAllByName0(host, true);
1186: }
1187:
1188: /**
1189: * package private so SocketPermission can call it
1190: */
1191: static InetAddress[] getAllByName0(String host, boolean check)
1192: throws UnknownHostException {
1193: /* If it gets here it is presumed to be a hostname */
1194: /* Cache.get can return: null, unknownAddress, or InetAddress[] */
1195: Object obj = null;
1196: Object objcopy = null;
1197:
1198: /* make sure the connection to the host is allowed, before we
1199: * give out a hostname
1200: */
1201: if (check) {
1202: SecurityManager security = System.getSecurityManager();
1203: if (security != null) {
1204: security.checkConnect(host, -1);
1205: }
1206: }
1207:
1208: obj = getCachedAddress(host);
1209:
1210: /* If no entry in cache, then do the host lookup */
1211: if (obj == null) {
1212: obj = getAddressFromNameService(host);
1213: }
1214:
1215: if (obj == unknown_array)
1216: throw new UnknownHostException(host);
1217:
1218: /* Make a copy of the InetAddress array */
1219: objcopy = ((InetAddress[]) obj).clone();
1220:
1221: return (InetAddress[]) objcopy;
1222: }
1223:
1224: private static Object getAddressFromNameService(String host)
1225: throws UnknownHostException {
1226: Object obj = null;
1227: boolean success = false;
1228: UnknownHostException ex = null;
1229:
1230: // Check whether the host is in the lookupTable.
1231: // 1) If the host isn't in the lookupTable when
1232: // checkLookupTable() is called, checkLookupTable()
1233: // would add the host in the lookupTable and
1234: // return null. So we will do the lookup.
1235: // 2) If the host is in the lookupTable when
1236: // checkLookupTable() is called, the current thread
1237: // would be blocked until the host is removed
1238: // from the lookupTable. Then this thread
1239: // should try to look up the addressCache.
1240: // i) if it found the address in the
1241: // addressCache, checkLookupTable() would
1242: // return the address.
1243: // ii) if it didn't find the address in the
1244: // addressCache for any reason,
1245: // it should add the host in the
1246: // lookupTable and return null so the
1247: // following code would do a lookup itself.
1248: if ((obj = checkLookupTable(host)) == null) {
1249: // This is the first thread which looks up the address
1250: // this host or the cache entry for this host has been
1251: // expired so this thread should do the lookup.
1252: for (NameService nameService : nameServices) {
1253: try {
1254: /*
1255: * Do not put the call to lookup() inside the
1256: * constructor. if you do you will still be
1257: * allocating space when the lookup fails.
1258: */
1259:
1260: obj = nameService.lookupAllHostAddr(host);
1261: success = true;
1262: break;
1263: } catch (UnknownHostException uhe) {
1264: if (host.equalsIgnoreCase("localhost")) {
1265: InetAddress[] local = new InetAddress[] { impl
1266: .loopbackAddress() };
1267: obj = local;
1268: success = true;
1269: break;
1270: } else {
1271: obj = unknown_array;
1272: success = false;
1273: ex = uhe;
1274: }
1275: }
1276: }
1277:
1278: // Cache the address.
1279: cacheAddress(host, obj, success);
1280: // Delete the host from the lookupTable, and
1281: // notify all threads waiting for the monitor
1282: // for lookupTable.
1283: updateLookupTable(host);
1284: if (!success && ex != null)
1285: throw ex;
1286: }
1287:
1288: return obj;
1289: }
1290:
1291: private static Object checkLookupTable(String host) {
1292: // make sure obj is null.
1293: Object obj = null;
1294:
1295: synchronized (lookupTable) {
1296: // If the host isn't in the lookupTable, add it in the
1297: // lookuptable and return null. The caller should do
1298: // the lookup.
1299: if (lookupTable.containsKey(host) == false) {
1300: lookupTable.put(host, null);
1301: return obj;
1302: }
1303:
1304: // If the host is in the lookupTable, it means that another
1305: // thread is trying to look up the address of this host.
1306: // This thread should wait.
1307: while (lookupTable.containsKey(host)) {
1308: try {
1309: lookupTable.wait();
1310: } catch (InterruptedException e) {
1311: }
1312: }
1313: }
1314:
1315: // The other thread has finished looking up the address of
1316: // the host. This thread should retry to get the address
1317: // from the addressCache. If it doesn't get the address from
1318: // the cache, it will try to look up the address itself.
1319: obj = getCachedAddress(host);
1320: if (obj == null) {
1321: synchronized (lookupTable) {
1322: lookupTable.put(host, null);
1323: }
1324: }
1325:
1326: return obj;
1327: }
1328:
1329: private static void updateLookupTable(String host) {
1330: synchronized (lookupTable) {
1331: lookupTable.remove(host);
1332: lookupTable.notifyAll();
1333: }
1334: }
1335:
1336: /**
1337: * Returns an <code>InetAddress</code> object given the raw IP address .
1338: * The argument is in network byte order: the highest order
1339: * byte of the address is in <code>getAddress()[0]</code>.
1340: *
1341: * <p> This method doesn't block, i.e. no reverse name service lookup
1342: * is performed.
1343: *
1344: * <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
1345: * must be 16 bytes long
1346: *
1347: * @param addr the raw IP address in network byte order
1348: * @return an InetAddress object created from the raw IP address.
1349: * @exception UnknownHostException if IP address is of illegal length
1350: * @since 1.4
1351: */
1352: public static InetAddress getByAddress(byte[] addr)
1353: throws UnknownHostException {
1354: return getByAddress(null, addr);
1355: }
1356:
1357: private static InetAddress cachedLocalHost = null;
1358: private static long cacheTime = 0;
1359: private static final long maxCacheTime = 5000L;
1360: private static final Object cacheLock = new Object();
1361:
1362: /**
1363: * Returns the address of the local host. This is achieved by retrieving
1364: * the name of the host from the system, then resolving that name into
1365: * an <code>InetAddress</code>.
1366: *
1367: * <P>Note: The resolved address may be cached for a short period of time.
1368: * </P>
1369: *
1370: * <p>If there is a security manager, its
1371: * <code>checkConnect</code> method is called
1372: * with the local host name and <code>-1</code>
1373: * as its arguments to see if the operation is allowed.
1374: * If the operation is not allowed, an InetAddress representing
1375: * the loopback address is returned.
1376: *
1377: * @return the address of the local host.
1378: *
1379: * @exception UnknownHostException if the local host name could not
1380: * be resolved into an address.
1381: *
1382: * @see SecurityManager#checkConnect
1383: * @see java.net.InetAddress#getByName(java.lang.String)
1384: */
1385: public static InetAddress getLocalHost()
1386: throws UnknownHostException {
1387:
1388: SecurityManager security = System.getSecurityManager();
1389: try {
1390: String local = impl.getLocalHostName();
1391:
1392: if (security != null) {
1393: security.checkConnect(local, -1);
1394: }
1395:
1396: if (local.equals("localhost")) {
1397: return impl.loopbackAddress();
1398: }
1399:
1400: InetAddress ret = null;
1401: synchronized (cacheLock) {
1402: long now = System.currentTimeMillis();
1403: if (cachedLocalHost != null) {
1404: if ((now - cacheTime) < maxCacheTime) // Less than 5s old?
1405: ret = cachedLocalHost;
1406: else
1407: cachedLocalHost = null;
1408: }
1409:
1410: // we are calling getAddressFromNameService directly
1411: // to avoid getting localHost from cache
1412: if (ret == null) {
1413: InetAddress[] localAddrs;
1414: try {
1415: localAddrs = (InetAddress[]) InetAddress
1416: .getAddressFromNameService(local);
1417: } catch (UnknownHostException uhe) {
1418: throw new UnknownHostException(local + ": "
1419: + uhe.getMessage());
1420: }
1421: cachedLocalHost = localAddrs[0];
1422: cacheTime = now;
1423: ret = localAddrs[0];
1424: }
1425: }
1426: return ret;
1427: } catch (java.lang.SecurityException e) {
1428: return impl.loopbackAddress();
1429: }
1430: }
1431:
1432: /**
1433: * Perform class load-time initializations.
1434: */
1435: private static native void init();
1436:
1437: /*
1438: * Returns the InetAddress representing anyLocalAddress
1439: * (typically 0.0.0.0 or ::0)
1440: */
1441: static InetAddress anyLocalAddress() {
1442: return impl.anyLocalAddress();
1443: }
1444:
1445: /*
1446: * Load and instantiate an underlying impl class
1447: */
1448: static Object loadImpl(String implName) {
1449: Object impl;
1450:
1451: /*
1452: * Property "impl.prefix" will be prepended to the classname
1453: * of the implementation object we instantiate, to which we
1454: * delegate the real work (like native methods). This
1455: * property can vary across implementations of the java.
1456: * classes. The default is an empty String "".
1457: */
1458: String prefix = (String) AccessController
1459: .doPrivileged(new GetPropertyAction("impl.prefix", ""));
1460: impl = null;
1461: try {
1462: impl = Class.forName("java.net." + prefix + implName)
1463: .newInstance();
1464: } catch (ClassNotFoundException e) {
1465: System.err.println("Class not found: java.net." + prefix
1466: + implName + ":\ncheck impl.prefix property "
1467: + "in your properties file.");
1468: } catch (InstantiationException e) {
1469: System.err.println("Could not instantiate: java.net."
1470: + prefix + implName
1471: + ":\ncheck impl.prefix property "
1472: + "in your properties file.");
1473: } catch (IllegalAccessException e) {
1474: System.err.println("Cannot access class: java.net."
1475: + prefix + implName
1476: + ":\ncheck impl.prefix property "
1477: + "in your properties file.");
1478: }
1479:
1480: if (impl == null) {
1481: try {
1482: impl = Class.forName(implName).newInstance();
1483: } catch (Exception e) {
1484: throw new Error("System property impl.prefix incorrect");
1485: }
1486: }
1487:
1488: return impl;
1489: }
1490: }
1491:
1492: /*
1493: * Simple factory to create the impl
1494: */
1495: class InetAddressImplFactory {
1496:
1497: static InetAddressImpl create() {
1498: Object o;
1499: if (isIPv6Supported()) {
1500: o = InetAddress.loadImpl("Inet6AddressImpl");
1501: } else {
1502: o = InetAddress.loadImpl("Inet4AddressImpl");
1503: }
1504: return (InetAddressImpl) o;
1505: }
1506:
1507: static native boolean isIPv6Supported();
1508: }
|