001: /*
002: * @(#)InetSocketAddress.java 1.18 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026: package java.net;
027:
028: import java.io.ObjectInputStream;
029: import java.io.IOException;
030: import java.io.InvalidObjectException;
031:
032: /**
033: *
034: * This class implements an IP Socket Address (IP address + port number)
035: * It can also be a pair (hostname + port number), in which case an attempt
036: * will be made to resolve the hostname. If resolution fails then the address
037: * is said to be <I>unresolved</I> but can still be used on some circumstances
038: * like connecting through a proxy.
039: * <p>
040: * It provides an immutable object used by sockets for binding, connecting, or
041: * as returned values.
042: * <p>
043: * The <i>wildcard</i> is a special local IP address. It usually means "any"
044: * and can only be used for <code>bind</code> operations.
045: *
046: * @see java.net.Socket
047: * @see java.net.ServerSocket
048: * @since 1.4
049: */
050: public class InetSocketAddress extends SocketAddress {
051: /* The hostname of the Socket Address
052: * @serial
053: */
054: private String hostname = null;
055: /* The IP address of the Socket Address
056: * @serial
057: */
058: private InetAddress addr = null;
059: /* The port number of the Socket Address
060: * @serial
061: */
062: private int port;
063:
064: private static final long serialVersionUID = 5076001401234631237L;
065:
066: /**
067: * Creates a socket address where the IP address is the wildcard address
068: * and the port number a specified value.
069: * <p>
070: * A valid port value is between 0 and 65535.
071: * A port number of <code>zero</code> will let the system pick up an
072: * ephemeral port in a <code>bind</code> operation.
073: * <p>
074: * @param port The port number
075: * @throws IllegalArgumentException if the port parameter is outside the specified
076: * range of valid port values.
077: */
078: public InetSocketAddress(int port) {
079: this (InetAddress.anyLocalAddress(), port);
080: }
081:
082: /**
083: *
084: * Creates a socket address from an IP address and a port number.
085: * <p>
086: * A valid port value is between 0 and 65535.
087: * A port number of <code>zero</code> will let the system pick up an
088: * ephemeral port in a <code>bind</code> operation.
089: * <P>
090: * A <code>null</code> address will assign the <i>wildcard</i> address.
091: * <p>
092: * @param addr The IP address
093: * @param port The port number
094: * @throws IllegalArgumentException if the port parameter is outside the specified
095: * range of valid port values.
096: */
097: public InetSocketAddress(InetAddress addr, int port) {
098: if (port < 0 || port > 0xFFFF) {
099: throw new IllegalArgumentException("port out of range:"
100: + port);
101: }
102: this .port = port;
103: if (addr == null)
104: this .addr = InetAddress.anyLocalAddress();
105: else
106: this .addr = addr;
107: }
108:
109: /**
110: *
111: * Creates a socket address from a hostname and a port number.
112: * <p>
113: * An attempt will be made to resolve the hostname into an InetAddress.
114: * If that attempt fails, the address will be flagged as <I>unresolved</I>.
115: * <p>
116: * A valid port value is between 0 and 65535.
117: * A port number of <code>zero</code> will let the system pick up an
118: * ephemeral port in a <code>bind</code> operation.
119: * <P>
120: * @param hostname the Host name
121: * @param port The port number
122: * @throws IllegalArgumentException if the port parameter is outside the range
123: * of valid port values, or if the hostname parameter is <TT>null</TT>.
124: * @see #isUnresolved()
125: */
126: public InetSocketAddress(String hostname, int port) {
127: if (port < 0 || port > 0xFFFF) {
128: throw new IllegalArgumentException("port out of range:"
129: + port);
130: }
131: if (hostname == null) {
132: throw new IllegalArgumentException("hostname can't be null");
133: }
134: try {
135: addr = InetAddress.getByName(hostname);
136: } catch (UnknownHostException e) {
137: this .hostname = hostname;
138: addr = null;
139: }
140: this .port = port;
141: }
142:
143: private void readObject(ObjectInputStream s) throws IOException,
144: ClassNotFoundException {
145: s.defaultReadObject();
146:
147: // Check that our invariants are satisfied
148: if (port < 0 || port > 0xFFFF) {
149: throw new InvalidObjectException("port out of range:"
150: + port);
151: }
152:
153: if (hostname == null && addr == null) {
154: throw new InvalidObjectException("hostname and addr "
155: + "can't both be null");
156: }
157: }
158:
159: /**
160: * Gets the port number.
161: *
162: * @return the port number.
163: */
164: public final int getPort() {
165: return port;
166: }
167:
168: /**
169: *
170: * Gets the <code>InetAddress</code>.
171: *
172: * @return the InetAdress or <code>null</code> if it is unresolved.
173: */
174: public final InetAddress getAddress() {
175: return addr;
176: }
177:
178: /**
179: * Gets the <code>hostname</code>.
180: *
181: * @return the hostname part of the address.
182: */
183: public final String getHostName() {
184: if (hostname != null)
185: return hostname;
186: if (addr != null)
187: return addr.getHostName();
188: return null;
189: }
190:
191: /**
192: * Checks wether the address has been resolved or not.
193: *
194: * @return <code>true</code> if the hostname couldn't be resolved into
195: * an <code>InetAddress</code>.
196: */
197: public final boolean isUnresolved() {
198: return addr == null;
199: }
200:
201: /**
202: * Constructs a string representation of this InetSocketAddress.
203: * This String is constructed by calling toString() on the InetAddress
204: * and concatenating the port number (with a colon). If the address
205: * is unresolved then the part before the colon will only contain the hostname.
206: *
207: * @return a string representation of this object.
208: */
209: public String toString() {
210: if (isUnresolved()) {
211: return hostname + ":" + port;
212: } else {
213: return addr.toString() + ":" + port;
214: }
215: }
216:
217: /**
218: * Compares this object against the specified object.
219: * The result is <code>true</code> if and only if the argument is
220: * not <code>null</code> and it represents the same address as
221: * this object.
222: * <p>
223: * Two instances of <code>InetSocketAddress</code> represent the same
224: * address if both the InetAddresses (or hostnames if it is unresolved) and port
225: * numbers are equal.
226: * If both addresses are unresolved, then the hostname & the port number
227: * are compared.
228: *
229: * @param obj the object to compare against.
230: * @return <code>true</code> if the objects are the same;
231: * <code>false</code> otherwise.
232: * @see java.net.InetAddress#equals(java.lang.Object)
233: */
234: public final boolean equals(Object obj) {
235: if (obj == null || !(obj instanceof InetSocketAddress))
236: return false;
237: InetSocketAddress sockAddr = (InetSocketAddress) obj;
238: boolean sameIP = false;
239: if (this .addr != null)
240: sameIP = this .addr.equals(sockAddr.addr);
241: else if (this .hostname != null)
242: sameIP = (sockAddr.addr == null)
243: && this .hostname.equals(sockAddr.hostname);
244: else
245: sameIP = (sockAddr.addr == null)
246: && (sockAddr.hostname == null);
247: return sameIP && (this .port == sockAddr.port);
248: }
249:
250: /**
251: * Returns a hashcode for this socket address.
252: *
253: * @return a hash code value for this socket address.
254: */
255: public final int hashCode() {
256: if (addr != null)
257: return addr.hashCode() + port;
258: if (hostname != null)
259: return hostname.hashCode() + port;
260: return port;
261: }
262: }
|