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