InetSocketAddress.java revision fd6bb3510c2f94d636f3572dcf5f7f4dcd1a2726
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.net;
19
20import java.io.IOException;
21import java.io.ObjectInputStream;
22
23/**
24 * This class represents a socket endpoint described by a IP address and a port
25 * number. It is a concrete implementation of {@code SocketAddress} for IP.
26 */
27public class InetSocketAddress extends SocketAddress {
28
29    private static final long serialVersionUID = 5076001401234631237L;
30
31    private String hostname;
32
33    private InetAddress addr;
34
35    private int port;
36
37    /**
38     * Creates a socket endpoint with the given port number {@code port} and
39     * no specified address. The range for valid port numbers is between 0 and
40     * 65535 inclusive.
41     *
42     * @param port
43     *            the specified port number to which this socket is bound.
44     */
45    public InetSocketAddress(int port) {
46        this((InetAddress) null, port);
47    }
48
49    /**
50     * Creates a socket endpoint with the given port number {@code port} and
51     * {@code address}. The range for valid port numbers is between 0 and 65535
52     * inclusive. If {@code address} is {@code null} this socket is bound to the
53     * IPv4 wildcard address.
54     *
55     * @param port
56     *            the specified port number to which this socket is bound.
57     * @param address
58     *            the specified address to which this socket is bound.
59     */
60    public InetSocketAddress(InetAddress address, int port) {
61        if (port < 0 || port > 65535) {
62            throw new IllegalArgumentException();
63        }
64        if (address == null) {
65            addr = Inet4Address.ANY;
66        } else {
67            addr = address;
68        }
69        hostname = addr.getHostName();
70        this.port = port;
71    }
72
73    /**
74     * Creates a socket endpoint with the given port number {@code port} and the
75     * hostname {@code host}. The hostname is tried to be resolved and cannot be
76     * {@code null}. The range for valid port numbers is between 0 and 65535
77     * inclusive.
78     *
79     * @param port
80     *            the specified port number to which this socket is bound.
81     * @param host
82     *            the specified hostname to which this socket is bound.
83     * @throws SecurityException
84     *             if a {@link SecurityManager} is installed and its {@code
85     *             checkConnect()} method does not allow the resolving of the
86     *             host name.
87     */
88    public InetSocketAddress(String host, int port) {
89        this(host, port, true);
90    }
91
92    /*
93     * Internal constructor for InetSocketAddress(String, int) and
94     * createUnresolved(String, int);
95     */
96    InetSocketAddress(String host, int port, boolean needResolved) {
97        if (host == null || port < 0 || port > 65535) {
98            throw new IllegalArgumentException();
99        }
100        hostname = host;
101        this.port = port;
102        if (needResolved) {
103            // BEGIN android-added
104            SecurityManager smgr = System.getSecurityManager();
105            if(smgr != null) {
106                smgr.checkConnect(host, port);
107            }
108            // END android-added
109            try {
110                addr = InetAddress.getByName(hostname);
111                hostname = null;
112            } catch (UnknownHostException e) {
113                // Ignored
114            }
115        } else {
116            addr = null;
117        }
118    }
119
120    /**
121     * Creates an {@code InetSocketAddress} without trying to resolve the
122     * hostname into an {@code InetAddress}. The address field is marked as
123     * unresolved.
124     *
125     * @param host
126     *            the specified hostname to which this socket is bound.
127     * @param port
128     *            the specified port number to which this socket is bound.
129     * @return the created InetSocketAddress instance.
130     * @throws IllegalArgumentException
131     *             if the hostname {@code host} is {@code null} or the port is
132     *             not in the range between 0 and 65535.
133     */
134    public static InetSocketAddress createUnresolved(String host, int port) {
135        return new InetSocketAddress(host, port, false);
136    }
137
138    /**
139     * Gets the port number of this socket.
140     *
141     * @return the socket endpoint port number.
142     */
143    public final int getPort() {
144        return port;
145    }
146
147    /**
148     * Gets the address of this socket.
149     *
150     * @return the socket endpoint address.
151     */
152    public final InetAddress getAddress() {
153        return addr;
154    }
155
156    /**
157     * Gets the hostname of this socket.
158     *
159     * @return the socket endpoint hostname.
160     */
161    public final String getHostName() {
162        return (null != addr) ? addr.getHostName() : hostname;
163    }
164
165    /**
166     * Returns whether this socket address is unresolved or not.
167     *
168     * @return {@code true} if this socket address is unresolved, {@code false}
169     *         otherwise.
170     */
171    public final boolean isUnresolved() {
172        return addr == null;
173    }
174
175    /**
176     * Gets a string representation of this socket included the address and the
177     * port number.
178     *
179     * @return the address and port number as a textual representation.
180     */
181    @Override
182    public String toString() {
183        String host;
184        if (addr != null) {
185            host = addr.toString();
186        } else {
187            host = hostname;
188        }
189        return host + ":" + port;
190    }
191
192    /**
193     * Compares two socket endpoints and returns true if they are equal. Two
194     * socket endpoints are equal if the IP address or the hostname of both are
195     * equal and they are bound to the same port.
196     *
197     * @param socketAddr
198     *            the object to be tested for equality.
199     * @return {@code true} if this socket and the given socket object {@code
200     *         socketAddr} are equal, {@code false} otherwise.
201     */
202    @Override
203    public final boolean equals(Object socketAddr) {
204        if (this == socketAddr) {
205            return true;
206        }
207        if (!(socketAddr instanceof InetSocketAddress)) {
208            return false;
209        }
210        InetSocketAddress iSockAddr = (InetSocketAddress) socketAddr;
211
212        // check the ports as we always need to do this
213        if (port != iSockAddr.port) {
214            return false;
215        }
216
217        // we only use the hostnames in the comparison if the addrs were not
218        // resolved
219        if ((addr == null) && (iSockAddr.addr == null)) {
220            return hostname.equals(iSockAddr.hostname);
221        }
222
223        // addrs were resolved so use them for the comparison
224        if (addr == null) {
225            // if we are here we know iSockAddr is not null so just return
226            // false
227            return false;
228        }
229        return addr.equals(iSockAddr.addr);
230    }
231
232    /**
233     * Gets the hashcode of this socket.
234     *
235     * @return the appropriate hashcode.
236     */
237    @Override
238    public final int hashCode() {
239        if (addr == null) {
240            return hostname.hashCode() + port;
241        }
242        return addr.hashCode() + port;
243    }
244
245    private void readObject(ObjectInputStream stream) throws IOException,
246            ClassNotFoundException {
247        stream.defaultReadObject();
248    }
249}
250