blob: 74c63d1ed6c3370f900a039c71d977e7f4539e7b [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package java.net;
26
27import java.io.ObjectInputStream;
28import java.io.IOException;
29import java.io.InvalidObjectException;
30
31/**
32 *
33 * This class implements an IP Socket Address (IP address + port number)
34 * It can also be a pair (hostname + port number), in which case an attempt
35 * will be made to resolve the hostname. If resolution fails then the address
36 * is said to be <I>unresolved</I> but can still be used on some circumstances
37 * like connecting through a proxy.
38 * <p>
39 * It provides an immutable object used by sockets for binding, connecting, or
40 * as returned values.
41 * <p>
42 * The <i>wildcard</i> is a special local IP address. It usually means "any"
43 * and can only be used for <code>bind</code> operations.
44 *
45 * @see java.net.Socket
46 * @see java.net.ServerSocket
47 * @since 1.4
48 */
49public class InetSocketAddress extends SocketAddress {
50 /* The hostname of the Socket Address
51 * @serial
52 */
53 private String hostname = null;
54 /* The IP address of the Socket Address
55 * @serial
56 */
57 private InetAddress addr = null;
58 /* The port number of the Socket Address
59 * @serial
60 */
61 private int port;
62
63 private static final long serialVersionUID = 5076001401234631237L;
64
65 private InetSocketAddress() {
66 }
67
68 /**
69 * Creates a socket address where the IP address is the wildcard address
70 * and the port number a specified value.
71 * <p>
72 * A valid port value is between 0 and 65535.
73 * A port number of <code>zero</code> will let the system pick up an
74 * ephemeral port in a <code>bind</code> operation.
75 * <p>
76 * @param port The port number
77 * @throws IllegalArgumentException if the port parameter is outside the specified
78 * range of valid port values.
79 */
80 public InetSocketAddress(int port) {
81 this(InetAddress.anyLocalAddress(), port);
82 }
83
84 /**
85 *
86 * Creates a socket address from an IP address and a port number.
87 * <p>
88 * A valid port value is between 0 and 65535.
89 * A port number of <code>zero</code> will let the system pick up an
90 * ephemeral port in a <code>bind</code> operation.
91 * <P>
92 * A <code>null</code> address will assign the <i>wildcard</i> address.
93 * <p>
94 * @param addr The IP address
95 * @param port The port number
96 * @throws IllegalArgumentException if the port parameter is outside the specified
97 * range of valid port values.
98 */
99 public InetSocketAddress(InetAddress addr, int port) {
100 if (port < 0 || port > 0xFFFF) {
101 throw new IllegalArgumentException("port out of range:" + port);
102 }
103 this.port = port;
104 if (addr == null)
105 this.addr = InetAddress.anyLocalAddress();
106 else
107 this.addr = addr;
108 }
109
110 /**
111 *
112 * Creates a socket address from a hostname and a port number.
113 * <p>
114 * An attempt will be made to resolve the hostname into an InetAddress.
115 * If that attempt fails, the address will be flagged as <I>unresolved</I>.
116 * <p>
117 * If there is a security manager, its <code>checkConnect</code> method
118 * is called with the host name as its argument to check the permissiom
119 * to resolve it. This could result in a SecurityException.
120 * <P>
121 * A valid port value is between 0 and 65535.
122 * A port number of <code>zero</code> will let the system pick up an
123 * ephemeral port in a <code>bind</code> operation.
124 * <P>
125 * @param hostname the Host name
126 * @param port The port number
127 * @throws IllegalArgumentException if the port parameter is outside the range
128 * of valid port values, or if the hostname parameter is <TT>null</TT>.
129 * @throws SecurityException if a security manager is present and
130 * permission to resolve the host name is
131 * denied.
132 * @see #isUnresolved()
133 */
134 public InetSocketAddress(String hostname, int port) {
135 if (port < 0 || port > 0xFFFF) {
136 throw new IllegalArgumentException("port out of range:" + port);
137 }
138 if (hostname == null) {
139 throw new IllegalArgumentException("hostname can't be null");
140 }
141 try {
142 addr = InetAddress.getByName(hostname);
143 } catch(UnknownHostException e) {
144 this.hostname = hostname;
145 addr = null;
146 }
147 this.port = port;
148 }
149
150 /**
151 *
152 * Creates an unresolved socket address from a hostname and a port number.
153 * <p>
154 * No attempt will be made to resolve the hostname into an InetAddress.
155 * The address will be flagged as <I>unresolved</I>.
156 * <p>
157 * A valid port value is between 0 and 65535.
158 * A port number of <code>zero</code> will let the system pick up an
159 * ephemeral port in a <code>bind</code> operation.
160 * <P>
161 * @param host the Host name
162 * @param port The port number
163 * @throws IllegalArgumentException if the port parameter is outside
164 * the range of valid port values, or if the hostname
165 * parameter is <TT>null</TT>.
166 * @see #isUnresolved()
167 * @return a <code>InetSocketAddress</code> representing the unresolved
168 * socket address
169 * @since 1.5
170 */
171 public static InetSocketAddress createUnresolved(String host, int port) {
172 if (port < 0 || port > 0xFFFF) {
173 throw new IllegalArgumentException("port out of range:" + port);
174 }
175 if (host == null) {
176 throw new IllegalArgumentException("hostname can't be null");
177 }
178 InetSocketAddress s = new InetSocketAddress();
179 s.port = port;
180 s.hostname = host;
181 s.addr = null;
182 return s;
183 }
184
185 private void readObject(ObjectInputStream s)
186 throws IOException, ClassNotFoundException {
187 s.defaultReadObject();
188
189 // Check that our invariants are satisfied
190 if (port < 0 || port > 0xFFFF) {
191 throw new InvalidObjectException("port out of range:" + port);
192 }
193
194 if (hostname == null && addr == null) {
195 throw new InvalidObjectException("hostname and addr " +
196 "can't both be null");
197 }
198 }
199
200 /**
201 * Gets the port number.
202 *
203 * @return the port number.
204 */
205 public final int getPort() {
206 return port;
207 }
208
209 /**
210 *
211 * Gets the <code>InetAddress</code>.
212 *
213 * @return the InetAdress or <code>null</code> if it is unresolved.
214 */
215 public final InetAddress getAddress() {
216 return addr;
217 }
218
219 /**
220 * Gets the <code>hostname</code>.
221 * Note: This method may trigger a name service reverse lookup if the
222 * address was created with a literal IP address.
223 *
224 * @return the hostname part of the address.
225 */
226 public final String getHostName() {
227 if (hostname != null)
228 return hostname;
229 if (addr != null)
230 return addr.getHostName();
231 return null;
232 }
233
234 /**
235 * Returns the hostname, or the String form of the address if it
236 * doesn't have a hostname (it was created using a literal).
237 * This has the benefit of <b>not</b> attemptimg a reverse lookup.
238 *
239 * @return the hostname, or String representation of the address.
240 * @since 1.7
241 */
242 public final String getHostString() {
243 if (hostname != null)
244 return hostname;
245 if (addr != null) {
246 if (addr.hostName != null)
247 return addr.hostName;
248 else
249 return addr.getHostAddress();
250 }
251 return null;
252 }
253
254 /**
255 * Checks whether the address has been resolved or not.
256 *
257 * @return <code>true</code> if the hostname couldn't be resolved into
258 * an <code>InetAddress</code>.
259 */
260 public final boolean isUnresolved() {
261 return addr == null;
262 }
263
264 /**
265 * Constructs a string representation of this InetSocketAddress.
266 * This String is constructed by calling toString() on the InetAddress
267 * and concatenating the port number (with a colon). If the address
268 * is unresolved then the part before the colon will only contain the hostname.
269 *
270 * @return a string representation of this object.
271 */
272 public String toString() {
273 if (isUnresolved()) {
274 return hostname + ":" + port;
275 } else {
276 return addr.toString() + ":" + port;
277 }
278 }
279
280 /**
281 * Compares this object against the specified object.
282 * The result is <code>true</code> if and only if the argument is
283 * not <code>null</code> and it represents the same address as
284 * this object.
285 * <p>
286 * Two instances of <code>InetSocketAddress</code> represent the same
287 * address if both the InetAddresses (or hostnames if it is unresolved) and port
288 * numbers are equal.
289 * If both addresses are unresolved, then the hostname & the port number
290 * are compared.
291 *
292 * Note: Hostnames are case insensitive. e.g. "FooBar" and "foobar" are
293 * considered equal.
294 *
295 * @param obj the object to compare against.
296 * @return <code>true</code> if the objects are the same;
297 * <code>false</code> otherwise.
298 * @see java.net.InetAddress#equals(java.lang.Object)
299 */
300 public final boolean equals(Object obj) {
301 if (obj == null || !(obj instanceof InetSocketAddress))
302 return false;
303 InetSocketAddress sockAddr = (InetSocketAddress) obj;
304 boolean sameIP = false;
305 if (this.addr != null)
306 sameIP = this.addr.equals(sockAddr.addr);
307 else if (this.hostname != null)
308 sameIP = (sockAddr.addr == null) &&
309 this.hostname.equalsIgnoreCase(sockAddr.hostname);
310 else
311 sameIP = (sockAddr.addr == null) && (sockAddr.hostname == null);
312 return sameIP && (this.port == sockAddr.port);
313 }
314
315 /**
316 * Returns a hashcode for this socket address.
317 *
318 * @return a hash code value for this socket address.
319 */
320 public final int hashCode() {
321 if (addr != null)
322 return addr.hashCode() + port;
323 if (hostname != null)
324 return hostname.toLowerCase().hashCode() + port;
325 return port;
326 }
327}