InetSocketAddress.java revision adc854b798c1cfe3bfd4c27d68d5cee38ca617da
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 *
27 * @since Android 1.0
28 */
29public class InetSocketAddress extends SocketAddress {
30
31    private static final long serialVersionUID = 5076001401234631237L;
32
33    private String hostname;
34
35    private InetAddress addr;
36
37    private int port;
38
39    /**
40     * Creates a socket endpoint with the given port number {@code port} and the
41     * wildcard address {@code InetAddress.ANY}. The range for valid port numbers
42     * is between 0 and 65535 inclusive.
43     *
44     * @param port
45     *            the specified port number to which this socket is bound.
46     * @since Android 1.0
47     */
48    public InetSocketAddress(int port) {
49        this((InetAddress) null, port);
50    }
51
52    /**
53     * Creates a socket endpoint with the given port number {@code port} and
54     * {@code address}. The range for valid port numbers is between 0 and 65535
55     * inclusive. If {@code address} is {@code null} this socket is bound to the
56     * wildcard address {@code InetAddress.ANY}.
57     *
58     * @param port
59     *            the specified port number to which this socket is bound.
60     * @param address
61     *            the specified address to which this socket is bound.
62     * @since Android 1.0
63     */
64    public InetSocketAddress(InetAddress address, int port) {
65        if (port < 0 || port > 65535) {
66            throw new IllegalArgumentException();
67        }
68        if (address == null) {
69            addr = InetAddress.ANY;
70        } else {
71            addr = address;
72        }
73        hostname = addr.getHostName();
74        this.port = port;
75    }
76
77    /**
78     * Creates a socket endpoint with the given port number {@code port} and the
79     * hostname {@code host}. The hostname is tried to be resolved and cannot be
80     * {@code null}. The range for valid port numbers is between 0 and 65535
81     * inclusive.
82     *
83     * @param port
84     *            the specified port number to which this socket is bound.
85     * @param host
86     *            the specified hostname to which this socket is bound.
87     * @throws SecurityException
88     *             if a {@link SecurityManager} is installed and its {@code
89     *             checkConnect()} method does not allow the resolving of the
90     *             host name.
91     * @since Android 1.0
92     */
93    public InetSocketAddress(String host, int port) {
94        this(host, port, true);
95    }
96
97    /*
98     * Internal contructor for InetSocketAddress(String, int) and
99     * createUnresolved(String, int);
100     */
101    InetSocketAddress(String host, int port, boolean needResolved) {
102        if (host == null || port < 0 || port > 65535) {
103            throw new IllegalArgumentException();
104        }
105        hostname = host;
106        this.port = port;
107        if (needResolved) {
108            // BEGIN android-added
109            SecurityManager smgr = System.getSecurityManager();
110            if(smgr != null) {
111                smgr.checkConnect(host, port);
112            }
113            // END android-added
114            try {
115                addr = InetAddress.getByName(hostname);
116                hostname = null;
117            } catch (UnknownHostException e) {
118                // Ignored
119            }
120        } else {
121            addr = null;
122        }
123    }
124
125    /**
126     * Creates an {@code InetSocketAddress} without trying to resolve the
127     * hostname into an {@code InetAddress}. The address field is marked as
128     * unresolved.
129     *
130     * @param host
131     *            the specified hostname to which this socket is bound.
132     * @param port
133     *            the specified port number to which this socket is bound.
134     * @return the created InetSocketAddress instance.
135     * @throws IllegalArgumentException
136     *             if the hostname {@code host} is {@code null} or the port is
137     *             not in the range between 0 and 65535.
138     * @since Android 1.0
139     */
140    public static InetSocketAddress createUnresolved(String host, int port) {
141        return new InetSocketAddress(host, port, false);
142    }
143
144    /**
145     * Gets the port number of this socket.
146     *
147     * @return the socket endpoint port number.
148     * @since Android 1.0
149     */
150    public final int getPort() {
151        return port;
152    }
153
154    /**
155     * Gets the address of this socket.
156     *
157     * @return the socket endpoint address.
158     * @since Android 1.0
159     */
160    public final InetAddress getAddress() {
161        return addr;
162    }
163
164    /**
165     * Gets the hostname of this socket.
166     *
167     * @return the socket endpoint hostname.
168     * @since Android 1.0
169     */
170    public final String getHostName() {
171        return (null != addr) ? addr.getHostName() : hostname;
172    }
173
174    /**
175     * Returns whether this socket address is unresolved or not.
176     *
177     * @return {@code true} if this socket address is unresolved, {@code false}
178     *         otherwise.
179     * @since Android 1.0
180     */
181    public final boolean isUnresolved() {
182        return addr == null;
183    }
184
185    /**
186     * Gets a string representation of this socket included the address and the
187     * port number.
188     *
189     * @return the address and port number as a textual representation.
190     * @since Android 1.0
191     */
192    @Override
193    public String toString() {
194        String host;
195        if (addr != null) {
196            host = addr.toString();
197        } else {
198            host = hostname;
199        }
200        return host + ":" + port; //$NON-NLS-1$
201    }
202
203    /**
204     * Compares two socket endpoints and returns true if they are equal. Two
205     * socket endpoints are equal if the IP address or the hostname of both are
206     * equal and they are bound to the same port.
207     *
208     * @param socketAddr
209     *            the object to be tested for equality.
210     * @return {@code true} if this socket and the given socket object {@code
211     *         socketAddr} are equal, {@code false} otherwise.
212     * @since Android 1.0
213     */
214    @Override
215    public final boolean equals(Object socketAddr) {
216        if (this == socketAddr) {
217            return true;
218        }
219        if (!(socketAddr instanceof InetSocketAddress)) {
220            return false;
221        }
222        InetSocketAddress iSockAddr = (InetSocketAddress) socketAddr;
223
224        // check the ports as we always need to do this
225        if (port != iSockAddr.port) {
226            return false;
227        }
228
229        // we only use the hostnames in the comparison if the addrs were not
230        // resolved
231        if ((addr == null) && (iSockAddr.addr == null)) {
232            return hostname.equals(iSockAddr.hostname);
233        }
234
235        // addrs were resolved so use them for the comparison
236        if (addr == null) {
237            // if we are here we know iSockAddr is not null so just return
238            // false
239            return false;
240        }
241        return addr.equals(iSockAddr.addr);
242    }
243
244    /**
245     * Gets the hashcode of this socket.
246     *
247     * @return the appropriate hashcode.
248     * @since Android 1.0
249     */
250    @Override
251    public final int hashCode() {
252        if (addr == null) {
253            return hostname.hashCode() + port;
254        }
255        return addr.hashCode() + port;
256    }
257
258    private void readObject(ObjectInputStream stream) throws IOException,
259            ClassNotFoundException {
260        stream.defaultReadObject();
261    }
262}
263