EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.util]

COVERAGE SUMMARY FOR SOURCE FILE [NetUtils.java]

nameclass, %method, %block, %line, %
NetUtils.java100% (1/1)92%  (11/12)71%  (246/348)73%  (73.1/100)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class NetUtils100% (1/1)92%  (11/12)71%  (246/348)73%  (73.1/100)
NetUtils (): void 0%   (0/1)0%   (0/3)0%   (0/2)
getBindAddress (): InetAddress 100% (1/1)21%  (6/28)32%  (2.6/8)
getHostAddress (InetAddress): String 100% (1/1)30%  (8/27)60%  (3/5)
createServerSocket (int, boolean): ServerSocket 100% (1/1)44%  (4/9)33%  (1/3)
createServerSocketTry (int, boolean): ServerSocket 100% (1/1)62%  (38/61)70%  (7/10)
getHostName (String): String 100% (1/1)67%  (6/9)50%  (2/4)
createLoopbackSocket (int, boolean): Socket 100% (1/1)71%  (15/21)75%  (6/8)
getLocalAddress (): String 100% (1/1)83%  (43/52)81%  (17.8/22)
closeSilently (ServerSocket): ServerSocket 100% (1/1)88%  (7/8)80%  (4/5)
isLocalAddress (Socket): boolean 100% (1/1)89%  (34/38)88%  (7.9/9)
createSocket (String, int, boolean): Socket 100% (1/1)90%  (36/40)97%  (7.8/8)
createSocket (InetAddress, int, boolean): Socket 100% (1/1)94%  (49/52)88%  (14/16)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.util;
7 
8import java.io.IOException;
9import java.net.BindException;
10import java.net.Inet6Address;
11import java.net.InetAddress;
12import java.net.InetSocketAddress;
13import java.net.ServerSocket;
14import java.net.Socket;
15import java.net.UnknownHostException;
16 
17import org.h2.api.ErrorCode;
18import org.h2.engine.SysProperties;
19import org.h2.message.DbException;
20import org.h2.security.CipherFactory;
21 
22/**
23 * This utility class contains socket helper functions.
24 */
25public class NetUtils {
26 
27    private static final int CACHE_MILLIS = 1000;
28    private static InetAddress cachedBindAddress;
29    private static String cachedLocalAddress;
30    private static long cachedLocalAddressTime;
31 
32    private NetUtils() {
33        // utility class
34    }
35 
36    /**
37     * Create a loopback socket (a socket that is connected to localhost) on
38     * this port.
39     *
40     * @param port the port
41     * @param ssl if SSL should be used
42     * @return the socket
43     */
44    public static Socket createLoopbackSocket(int port, boolean ssl)
45            throws IOException {
46        InetAddress address = getBindAddress();
47        if (address == null) {
48            address = InetAddress.getLocalHost();
49        }
50        try {
51            return createSocket(getHostAddress(address), port, ssl);
52        } catch (IOException e) {
53            try {
54                return createSocket("localhost", port, ssl);
55            } catch (IOException e2) {
56                // throw the original exception
57                throw e;
58            }
59        }
60    }
61 
62    /**
63     * Get the host address. This method adds '[' and ']' if required for
64     * Inet6Address that contain a ':'.
65     *
66     * @param address the address
67     * @return the host address
68     */
69    private static String getHostAddress(InetAddress address) {
70        String host = address.getHostAddress();
71        if (address instanceof Inet6Address) {
72            if (host.indexOf(':') >= 0 && !host.startsWith("[")) {
73                host = "[" + host + "]";
74            }
75        }
76        return host;
77    }
78 
79    /**
80     * Create a client socket that is connected to the given address and port.
81     *
82     * @param server to connect to (including an optional port)
83     * @param defaultPort the default port (if not specified in the server
84     *            address)
85     * @param ssl if SSL should be used
86     * @return the socket
87     */
88    public static Socket createSocket(String server, int defaultPort,
89            boolean ssl) throws IOException {
90        int port = defaultPort;
91        // IPv6: RFC 2732 format is '[a:b:c:d:e:f:g:h]' or
92        // '[a:b:c:d:e:f:g:h]:port'
93        // RFC 2396 format is 'a.b.c.d' or 'a.b.c.d:port' or 'hostname' or
94        // 'hostname:port'
95        int startIndex = server.startsWith("[") ? server.indexOf(']') : 0;
96        int idx = server.indexOf(':', startIndex);
97        if (idx >= 0) {
98            port = Integer.decode(server.substring(idx + 1));
99            server = server.substring(0, idx);
100        }
101        InetAddress address = InetAddress.getByName(server);
102        return createSocket(address, port, ssl);
103    }
104 
105    /**
106     * Create a client socket that is connected to the given address and port.
107     *
108     * @param address the address to connect to
109     * @param port the port
110     * @param ssl if SSL should be used
111     * @return the socket
112     */
113    public static Socket createSocket(InetAddress address, int port, boolean ssl)
114            throws IOException {
115        long start = System.currentTimeMillis();
116        for (int i = 0;; i++) {
117            try {
118                if (ssl) {
119                    return CipherFactory.createSocket(address, port);
120                }
121                Socket socket = new Socket();
122                socket.connect(new InetSocketAddress(address, port),
123                        SysProperties.SOCKET_CONNECT_TIMEOUT);
124                return socket;
125            } catch (IOException e) {
126                if (System.currentTimeMillis() - start >=
127                        SysProperties.SOCKET_CONNECT_TIMEOUT) {
128                    // either it was a connect timeout,
129                    // or list of different exceptions
130                    throw e;
131                }
132                if (i >= SysProperties.SOCKET_CONNECT_RETRY) {
133                    throw e;
134                }
135                // wait a bit and retry
136                try {
137                    // sleep at most 256 ms
138                    long sleep = Math.min(256, i * i);
139                    Thread.sleep(sleep);
140                } catch (InterruptedException e2) {
141                    // ignore
142                }
143            }
144        }
145    }
146 
147    /**
148     * Create a server socket. The system property h2.bindAddress is used if
149     * set.
150     *
151     * @param port the port to listen on
152     * @param ssl if SSL should be used
153     * @return the server socket
154     */
155    public static ServerSocket createServerSocket(int port, boolean ssl) {
156        try {
157            return createServerSocketTry(port, ssl);
158        } catch (Exception e) {
159            // try again
160            return createServerSocketTry(port, ssl);
161        }
162    }
163 
164    /**
165     * Get the bind address if the system property h2.bindAddress is set, or
166     * null if not.
167     *
168     * @return the bind address
169     */
170    private static InetAddress getBindAddress() throws UnknownHostException {
171        String host = SysProperties.BIND_ADDRESS;
172        if (host == null || host.length() == 0) {
173            return null;
174        }
175        synchronized (NetUtils.class) {
176            if (cachedBindAddress == null) {
177                cachedBindAddress = InetAddress.getByName(host);
178            }
179        }
180        return cachedBindAddress;
181    }
182 
183    private static ServerSocket createServerSocketTry(int port, boolean ssl) {
184        try {
185            InetAddress bindAddress = getBindAddress();
186            if (ssl) {
187                return CipherFactory.createServerSocket(port, bindAddress);
188            }
189            if (bindAddress == null) {
190                return new ServerSocket(port);
191            }
192            return new ServerSocket(port, 0, bindAddress);
193        } catch (BindException be) {
194            throw DbException.get(ErrorCode.EXCEPTION_OPENING_PORT_2,
195                    be, "" + port, be.toString());
196        } catch (IOException e) {
197            throw DbException.convertIOException(e, "port: " + port + " ssl: " + ssl);
198        }
199    }
200 
201    /**
202     * Check if a socket is connected to a local address.
203     *
204     * @param socket the socket
205     * @return true if it is
206     */
207    public static boolean isLocalAddress(Socket socket)
208            throws UnknownHostException {
209        InetAddress test = socket.getInetAddress();
210        if (test.isLoopbackAddress()) {
211            return true;
212        }
213        InetAddress localhost = InetAddress.getLocalHost();
214        // localhost.getCanonicalHostName() is very very slow
215        String host = localhost.getHostAddress();
216        for (InetAddress addr : InetAddress.getAllByName(host)) {
217            if (test.equals(addr)) {
218                return true;
219            }
220        }
221        return false;
222    }
223 
224    /**
225     * Close a server socket and ignore any exceptions.
226     *
227     * @param socket the socket
228     * @return null
229     */
230    public static ServerSocket closeSilently(ServerSocket socket) {
231        if (socket != null) {
232            try {
233                socket.close();
234            } catch (IOException e) {
235                // ignore
236            }
237        }
238        return null;
239    }
240 
241    /**
242     * Get the local host address as a string.
243     * For performance, the result is cached for one second.
244     *
245     * @return the local host address
246     */
247    public static synchronized String getLocalAddress() {
248        long now = System.currentTimeMillis();
249        if (cachedLocalAddress != null) {
250            if (cachedLocalAddressTime + CACHE_MILLIS > now) {
251                return cachedLocalAddress;
252            }
253        }
254        InetAddress bind = null;
255        boolean useLocalhost = false;
256        try {
257            bind = getBindAddress();
258            if (bind == null) {
259                useLocalhost = true;
260            }
261        } catch (UnknownHostException e) {
262            // ignore
263        }
264        if (useLocalhost) {
265            try {
266                bind = InetAddress.getLocalHost();
267            } catch (UnknownHostException e) {
268                throw DbException.convert(e);
269            }
270        }
271        String address = bind == null ? "localhost" : getHostAddress(bind);
272        if (address.equals("127.0.0.1")) {
273            address = "localhost";
274        }
275        cachedLocalAddress = address;
276        cachedLocalAddressTime = now;
277        return address;
278    }
279 
280    /**
281     * Get the host name of a local address, if available.
282     *
283     * @param localAddress the local address
284     * @return the host name, or another text if not available
285     */
286    public static String getHostName(String localAddress) {
287        try {
288            InetAddress addr = InetAddress.getByName(localAddress);
289            return addr.getHostName();
290        } catch (Exception e) {
291            return "unknown";
292        }
293    }
294 
295}

[all classes][org.h2.util]
EMMA 2.0.5312 (C) Vladimir Roubtsov